Skip to content

Commit

Permalink
Merge pull request #17500 from Coolthulhu/weather-gen
Browse files Browse the repository at this point in the history
[CR]Regional weather settings
  • Loading branch information
mugling committed Sep 14, 2016
2 parents ee310f0 + a3f11a9 commit 86f3574
Show file tree
Hide file tree
Showing 15 changed files with 125 additions and 90 deletions.
6 changes: 6 additions & 0 deletions data/json/regional_map_settings.json
Expand Up @@ -161,6 +161,12 @@
"veterinarian": 2,
"mortuary": 1
}
},
"weather": {
"base_temperature" : 6.5,
"base_humidity" : 66.0,
"base_pressure" : 1015.0,
"base_acid" : 0.0
}
}
]
6 changes: 6 additions & 0 deletions data/json/test_regions.json
Expand Up @@ -52,6 +52,12 @@
"police": 1,
"s_lot": 6
}
},
"weather": {
"base_temperature" : 8.0,
"base_humidity" : 40.0,
"base_pressure" : 1015.0,
"base_acid" : 0.0
}
},
{
Expand Down
4 changes: 1 addition & 3 deletions src/bionics.cpp
Expand Up @@ -19,7 +19,6 @@
#include "itype.h"
#include "vehicle.h"
#include "field.h"
#include "weather_gen.h"
#include "weather.h"
#include "cata_utility.h"
#include "output.h"
Expand Down Expand Up @@ -148,8 +147,7 @@ bool player::activate_bionic( int b, bool eff_only )
}

item tmp_item;
w_point const weatherPoint = g->weather_gen->get_weather( global_square_location(),
calendar::turn );
w_point const weatherPoint = *g->weather_precise;

// On activation effects go here
if( bionics[bio.id].gun_bionic ) {
Expand Down
30 changes: 22 additions & 8 deletions src/game.cpp
Expand Up @@ -221,7 +221,6 @@ game::game() :
u( *u_ptr ),
scent( *scent_ptr ),
critter_tracker( new Creature_tracker() ),
weather_gen( new weather_generator() ),
weather( WEATHER_CLEAR ),
lightning_active( false ),
weather_precise( new w_point() ),
Expand Down Expand Up @@ -783,10 +782,10 @@ bool game::start_game(std::string worldname)
gamemode.reset( new special_game() );
}

seed = rand();
new_game = true;
start_calendar();
nextweather = calendar::turn;
weather_gen->set_seed( rand() );
safe_mode = (get_option<bool>( "SAFEMODE" ) ? SAFE_MODE_ON : SAFE_MODE_OFF);
mostseen = 0; // ...and mostseen is 0, we haven't seen any monsters yet.

Expand Down Expand Up @@ -1704,21 +1703,36 @@ bool game::cancel_activity_query(const char *message, ...)
return false;
}

const weather_generator &game::get_cur_weather_gen() const
{
const auto &om = get_cur_om();
const auto &settings = om.get_settings();
return settings.weather;
}

unsigned int game::get_seed() const
{
return seed;
}

void game::update_weather()
{
if (calendar::turn >= nextweather) {
if( weather == WEATHER_NULL || calendar::turn >= nextweather ) {
const weather_generator &weather_gen = get_cur_weather_gen();
w_point &w = *weather_precise;
w = weather_gen->get_weather( u.global_square_location(), calendar::turn );
w = weather_gen.get_weather( u.global_square_location(), calendar::turn, seed );
weather_type old_weather = weather;
weather = weather_gen->get_weather_conditions(w);
weather = weather_override == WEATHER_NULL ?
weather_gen.get_weather_conditions( w )
: weather_override;
if( weather == WEATHER_SUNNY && calendar::turn.is_night() ) {
weather = WEATHER_CLEAR;
}
sfx::do_ambient();

temperature = w.temperature;
lightning_active = false;
nextweather += 50; // Check weather each 50 turns.
nextweather = calendar::turn + 50; // Check weather each 50 turns.
if (weather != old_weather && weather_data(weather).dangerous &&
get_levz() >= 0 && m.is_outside(u.pos())
&& !u.has_activity(ACT_WAIT_WEATHER)) {
Expand Down Expand Up @@ -4421,7 +4435,7 @@ void game::debug()
uimenu weather_menu;
weather_menu.text = _( "Select new weather pattern:" );
weather_menu.return_invalid = true;
weather_menu.addentry( 0, true, MENU_AUTOASSIGN, weather_gen->debug_weather == WEATHER_NULL ?
weather_menu.addentry( 0, true, MENU_AUTOASSIGN, weather_override == WEATHER_NULL ?
_( "Keep normal weather patterns" ) : _( "Disable weather forcing" ) );
for( int weather_id = 1; weather_id < NUM_WEATHER_TYPES; weather_id++ ) {
weather_menu.addentry( weather_id, true, MENU_AUTOASSIGN,
Expand All @@ -4434,7 +4448,7 @@ void game::debug()

if( weather_menu.ret >= 0 && weather_menu.ret <= NUM_WEATHER_TYPES ) {
weather_type selected_weather = ( weather_type )weather_menu.selected;
weather_gen->debug_weather = selected_weather;
weather_override = selected_weather;
nextweather = calendar::turn;
update_weather();
}
Expand Down
9 changes: 8 additions & 1 deletion src/game.h
Expand Up @@ -490,7 +490,6 @@ class game
void reset_zoom();
int get_user_action_counter() const;

std::unique_ptr<weather_generator> weather_gen;
signed char temperature; // The air temperature
int get_temperature(); // Returns outdoor or indoor temperature of current location
weather_type weather; // Weather pattern--SEE weather.h
Expand All @@ -513,6 +512,7 @@ class game
* The overmap which contains the center submap of the reality bubble.
*/
overmap &get_cur_om() const;
const weather_generator &get_cur_weather_gen() const;
const scenario *scen;
std::vector<monster> coming_to_stairs;
int monstairz;
Expand Down Expand Up @@ -793,6 +793,8 @@ class game
public:
bool unload( item &it ); // Unload a gun/tool 'U'
void unload(int pos = INT_MIN);

unsigned int get_seed() const;
private:
void wield(int pos = INT_MIN); // Wield a weapon 'w'
void read(); // Read a book 'R' (or 'a')
Expand Down Expand Up @@ -931,6 +933,11 @@ class game
/** How far the tileset should be zoomed out, 16 is default. 32 is zoomed in by x2, 8 is zoomed out by x0.5 */
int tileset_zoom;

/** Seed for all the random numbers that should have consistent randomness (weather). */
unsigned int seed;

weather_type weather_override;

// Preview for auto move route
std::vector<tripoint> destination_preview;

Expand Down
1 change: 1 addition & 0 deletions src/init.cpp
Expand Up @@ -53,6 +53,7 @@
#include "gates.h"
#include "overlay_ordering.h"
#include "worldfactory.h"
#include "weather_gen.h"
#include "npc_class.h"

#include <string>
Expand Down
4 changes: 1 addition & 3 deletions src/iuse.cpp
Expand Up @@ -37,7 +37,6 @@
#include "ui.h"
#include "mtype.h"
#include "field.h"
#include "weather_gen.h"
#include "weather.h"
#include "cata_utility.h"
#include "map_iterator.h"
Expand Down Expand Up @@ -7661,8 +7660,7 @@ int iuse::hairkit(player *p, item *it, bool, const tripoint&)

int iuse::weather_tool( player *p, item *it, bool, const tripoint& )
{
w_point const weatherPoint = g->weather_gen->get_weather( p->global_square_location(),
calendar::turn );
w_point const weatherPoint = *g->weather_precise;

if( it->typeId() == "weather_reader" ) {
p->add_msg_if_player( m_neutral, _( "The %s's monitor slowly outputs the data..." ),
Expand Down
27 changes: 19 additions & 8 deletions src/overmap.cpp
Expand Up @@ -679,6 +679,16 @@ void load_region_settings( JsonObject &jo )
}
}
}

if ( ! jo.has_object("weather") ) {
if ( strict ) {
jo.throw_error("\"weather\": { ... } required for default");
}
} else {
JsonObject wjo = jo.get_object( "weather" );
new_region.weather = weather_generator::load( wjo );
}

region_settings_map[new_region.id] = new_region;
}

Expand Down Expand Up @@ -1582,19 +1592,20 @@ std::tuple<char, nc_color, size_t> get_note_display_info(std::string const &note
return result;
}

static bool get_weather_glyph( point const &pos, nc_color &ter_color, long &ter_sym )
static bool get_weather_glyph( tripoint const &pos, nc_color &ter_color, long &ter_sym )
{
// Weather calculation is a bit expensive, so it's cached here.
static std::map<point, weather_type> weather_cache;
static std::map<tripoint, weather_type> weather_cache;
static calendar last_weather_display = calendar::turn;
if( last_weather_display != calendar::turn ) {
last_weather_display = calendar::turn;
weather_cache.clear();
}
auto iter = weather_cache.find( pos );
if( iter == weather_cache.end() ) {
auto const abs_ms_pos = point( pos.x * SEEX * 2, pos.y * SEEY * 2 );
auto const weather = g->weather_gen->get_weather_conditions( abs_ms_pos, calendar::turn );
auto const abs_ms_pos = tripoint( pos.x * SEEX * 2, pos.y * SEEY * 2, pos.z );
const auto &wgen = overmap_buffer.get_settings( pos.x, pos.y, pos.z ).weather;
auto const weather = wgen.get_weather_conditions( abs_ms_pos, calendar::turn, g->get_seed() );
iter = weather_cache.insert( std::make_pair( pos, weather ) ).first;
}
switch( iter->second ) {
Expand Down Expand Up @@ -1719,7 +1730,7 @@ void overmap::draw(WINDOW *w, WINDOW *wbar, const tripoint &center,

// For use with place_special: cache the color and symbol of each submap
// and record the bounds to optimize lookups below
std::unordered_map<point, std::pair<long, nc_color>> special_cache;
std::unordered_map<tripoint, std::pair<long, nc_color>> special_cache;
point s_begin, s_end = point( 0, 0 );
if( blink && uistate.place_special ) {
for( const auto &s_ter : uistate.place_special->terrains ) {
Expand All @@ -1732,7 +1743,7 @@ void overmap::draw(WINDOW *w, WINDOW *wbar, const tripoint &center,
}

special_cache.insert( std::make_pair(
point( rp.x, rp.y ),
rp,
std::make_pair( oter.t().sym, oter.t().color ) ) );

s_begin.x = std::min( s_begin.x, rp.x );
Expand Down Expand Up @@ -1796,7 +1807,7 @@ void overmap::draw(WINDOW *w, WINDOW *wbar, const tripoint &center,
// Display player pos, should always be visible
ter_color = g->u.symbol_color();
ter_sym = '@';
} else if( data.debug_weather && get_weather_glyph( point( omx, omy ), ter_color, ter_sym ) ) {
} else if( data.debug_weather && get_weather_glyph( tripoint( omx, omy, z ), ter_color, ter_sym ) ) {
// ter_color and ter_sym have been set by get_weather_glyph
} else if( data.debug_scent && get_scent_glyph( cur_pos, ter_color, ter_sym ) ) {
} else if( blink && has_target && omx == target.x && omy == target.y ) {
Expand Down Expand Up @@ -1912,7 +1923,7 @@ void overmap::draw(WINDOW *w, WINDOW *wbar, const tripoint &center,
} else if( blink && uistate.place_special ) {
if( omx - cursx >= s_begin.x && omx - cursx <= s_end.x &&
omy - cursy >= s_begin.y && omy - cursy <= s_end.y ) {
auto sm = special_cache.find( point( omx - cursx, omy - cursy ) );
auto sm = special_cache.find( tripoint( omx - cursx, omy - cursy, z ) );
if( sm != special_cache.end() ) {
ter_color = sm->second.second;
ter_sym = sm->second.first;
Expand Down
11 changes: 6 additions & 5 deletions src/overmap.h
Expand Up @@ -7,6 +7,7 @@
#include "weighted_list.h"
#include "game_constants.h"
#include "monster.h"
#include "weather_gen.h"

#include <array>
#include <iosfwd>
Expand Down Expand Up @@ -126,6 +127,8 @@ struct regional_settings {
groundcover_extra field_coverage;
groundcover_extra forest_coverage;

weather_generator weather;

std::unordered_map<std::string, map_extras> region_extras;

regional_settings() : id("null"), default_oter("field"), default_groundcover(t_null, 0, t_null) { }
Expand Down Expand Up @@ -306,11 +309,9 @@ class overmap
/** Get the y coordinate of the bottom border of this overmap. */
int get_bottom_border();

const regional_settings& get_settings(const int x, const int y, const int z) {
(void)x;
(void)y;
(void)z; // todo

// @todo Should depend on coords
const regional_settings& get_settings() const
{
return settings;
}
void clear_mon_groups();
Expand Down
3 changes: 2 additions & 1 deletion src/overmapbuffer.cpp
Expand Up @@ -120,8 +120,9 @@ void overmapbuffer::clear()

const regional_settings& overmapbuffer::get_settings(int x, int y, int z)
{
(void)z;
overmap &om = get_om_global(x, y);
return om.get_settings(x, y, z);
return om.get_settings();
}

void overmapbuffer::add_note(int x, int y, int z, const std::string& message)
Expand Down
4 changes: 2 additions & 2 deletions src/player.cpp
Expand Up @@ -758,7 +758,7 @@ void player::update_bodytemp()
// NOTE : visit weather.h for some details on the numbers used
// Converts temperature to Celsius/10
int Ctemperature = int( 100 * temp_to_celsius( g->get_temperature() ) );
w_point const weather = g->weather_gen->get_weather( global_square_location(), calendar::turn );
w_point const weather = *g->weather_precise;
int vpart = -1;
vehicle *veh = g->m.veh_at( pos(), vpart );
int vehwindspeed = 0;
Expand Down Expand Up @@ -835,6 +835,7 @@ void player::update_bodytemp()
}

const int lying_warmth = use_floor_warmth ? floor_warmth( pos() ) : 0;
const int water_temperature = 100 * temp_to_celsius( g->get_cur_weather_gen().get_water_temperature() );

// Current temperature and converging temperature calculations
for( int i = 0 ; i < num_bp; i++ ) {
Expand Down Expand Up @@ -867,7 +868,6 @@ void player::update_bodytemp()
// If you're standing in water, air temperature is replaced by water temperature. No wind.
const ter_id ter_at_pos = g->m.ter( pos() );
// Convert to 0.01C
int water_temperature = int( 100 * temp_to_celsius( g->weather_gen->get_water_temperature() ) );
if( ( ter_at_pos == t_water_dp || ter_at_pos == t_water_pool || ter_at_pos == t_swater_dp ) ||
( ( ter_at_pos == t_water_sh || ter_at_pos == t_swater_sh || ter_at_pos == t_sewage ) &&
( i == bp_foot_l || i == bp_foot_r || i == bp_leg_l || i == bp_leg_r ) ) ) {
Expand Down
4 changes: 1 addition & 3 deletions src/savegame.cpp
Expand Up @@ -291,17 +291,15 @@ void game::load_weather(std::istream & fin) {
if (fin.peek() == 's') {
std::string line, label;
getline(fin, line);
int seed(0);
std::stringstream liness(line);
liness >> label >> seed;
weather_gen->set_seed( seed );
}
}

void game::save_weather(std::ostream &fout) {
fout << "# version " << savegame_version << std::endl;
fout << "lightning: " << (lightning_active ? "1" : "0") << std::endl;
fout << "seed: " << weather_gen->get_seed();
fout << "seed: " << seed;
}

bool overmap::obsolete_terrain( const std::string &ter ) {
Expand Down
13 changes: 8 additions & 5 deletions src/weather.cpp
Expand Up @@ -70,8 +70,9 @@ int get_rot_since( const int startturn, const int endturn, const tripoint &locat
}
// TODO: maybe have different rotting speed when underground?
int ret = 0;
const auto &wgen = g->get_cur_weather_gen();
for (calendar i(startturn); i.get_turn() < endturn; i += 600) {
w_point w = g->weather_gen->get_weather(location, i);
w_point w = wgen.get_weather( location, i, g->get_seed() );
ret += std::min(600, endturn - i.get_turn()) * get_hourly_rotpoints_at_temp(w.temperature) / 600;
}
return ret;
Expand Down Expand Up @@ -112,6 +113,7 @@ weather_sum sum_conditions( const calendar &startturn,
int tick_size = MINUTES(1);
weather_sum data;

const auto wgen = g->get_cur_weather_gen();
for( calendar turn(startturn); turn < endturn; turn += tick_size ) {
const int diff = endturn - startturn;
if( diff <= 0 ) {
Expand All @@ -124,7 +126,7 @@ weather_sum sum_conditions( const calendar &startturn,
tick_size = MINUTES(1);
}

const auto wtype = g->weather_gen->get_weather_conditions( point( location.x, location.y ), turn );
const auto wtype = wgen.get_weather_conditions( location, turn, g->get_seed() );
proc_weather_sum( wtype, data, turn, tick_size );
}

Expand Down Expand Up @@ -542,14 +544,15 @@ std::string weather_forecast( point const &abs_sm_pos )
// int weather_proportions[NUM_WEATHER_TYPES] = {0};
double high = -100.0;
double low = 100.0;
point const abs_ms_pos = sm_to_ms_copy( abs_sm_pos );
const tripoint abs_ms_pos = tripoint( sm_to_ms_copy( abs_sm_pos ), 0 );
// 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;
const auto wgen = g->get_cur_weather_gen();
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));
w_point w = wgen.get_weather( abs_ms_pos, i, g->get_seed() );
forecast = std::max( forecast, wgen.get_weather_conditions( w ) );
high = std::max(high, w.temperature);
low = std::min(low, w.temperature);
}
Expand Down

0 comments on commit 86f3574

Please sign in to comment.