|
1 | 1 | #include "game.h"
|
| 2 | +#include "map_memory.h" |
2 | 3 |
|
3 | 4 | #include <algorithm>
|
4 | 5 | #include <bitset>
|
@@ -3186,6 +3187,15 @@ void game::load_master()
|
3186 | 3187 | } );
|
3187 | 3188 | }
|
3188 | 3189 |
|
| 3190 | +bool game::load_dimension_data() |
| 3191 | +{ |
| 3192 | + const cata_path datafile = PATH_INFO::current_dimension_save_path() / SAVE_DIMENSION_DATA; |
| 3193 | + // If dimension_data.gsav doesn't exist, return false |
| 3194 | + return read_from_file_optional( datafile, [this, &datafile]( std::istream & is ) { |
| 3195 | + unserialize_dimension_data( datafile, is ); |
| 3196 | + } ); |
| 3197 | +} |
| 3198 | + |
3189 | 3199 | bool game::load( const std::string &world )
|
3190 | 3200 | {
|
3191 | 3201 | world_generator->init();
|
@@ -3229,6 +3239,13 @@ bool game::load( const save_t &name )
|
3229 | 3239 | load_master();
|
3230 | 3240 | }
|
3231 | 3241 | },
|
| 3242 | + { |
| 3243 | + _( "Dimension data" ), [&]() |
| 3244 | + { |
| 3245 | + // Load up dimension specific data (ie; weather, overmapstate) |
| 3246 | + load_dimension_data(); |
| 3247 | + } |
| 3248 | + }, |
3232 | 3249 | {
|
3233 | 3250 | _( "Character save" ), [&]()
|
3234 | 3251 | {
|
@@ -3471,7 +3488,14 @@ bool game::save_factions_missions_npcs()
|
3471 | 3488 | serialize_master( fout );
|
3472 | 3489 | }, _( "factions data" ) );
|
3473 | 3490 | }
|
3474 |
| - |
| 3491 | +//Saves per-dimension data like Weather and overmapbuffer state |
| 3492 | +bool game::save_dimension_data() |
| 3493 | +{ |
| 3494 | + cata_path data_file = PATH_INFO::current_dimension_save_path() / SAVE_DIMENSION_DATA; |
| 3495 | + return write_to_file( data_file, [&]( std::ostream & fout ) { |
| 3496 | + serialize_dimension_data( fout ); |
| 3497 | + }, _( "dimension data" ) ); |
| 3498 | +} |
3475 | 3499 | bool game::save_maps()
|
3476 | 3500 | {
|
3477 | 3501 | map &here = get_map();
|
@@ -3641,6 +3665,7 @@ bool game::save()
|
3641 | 3665 | if( !save_player_data() ||
|
3642 | 3666 | !save_achievements() ||
|
3643 | 3667 | !save_factions_missions_npcs() ||
|
| 3668 | + !save_dimension_data() || |
3644 | 3669 | !save_maps() ||
|
3645 | 3670 | !get_auto_pickup().save_character() ||
|
3646 | 3671 | !get_auto_notes_settings().save( true ) ||
|
@@ -5698,7 +5723,7 @@ bool game::revive_corpse( const tripoint_bub_ms &p, item &it, int radius )
|
5698 | 5723 | }
|
5699 | 5724 | // If this is not here, the game may attempt to spawn a monster before the map exists,
|
5700 | 5725 | // leading to it querying for furniture, and crashing.
|
5701 |
| - if( g->new_game ) { |
| 5726 | + if( g->new_game || g->swapping_dimensions ) { |
5702 | 5727 | return false;
|
5703 | 5728 | }
|
5704 | 5729 | if( it.has_flag( flag_FIELD_DRESS ) || it.has_flag( flag_FIELD_DRESS_FAILED ) ||
|
@@ -11480,7 +11505,7 @@ void game::place_player_overmap( const tripoint_abs_omt &om_dest, bool move_play
|
11480 | 11505 | here.spawn_monsters( true ); // Static monsters
|
11481 | 11506 | update_overmap_seen();
|
11482 | 11507 | // update weather now as it could be different on the new location
|
11483 |
| - weather.nextweather = calendar::turn; |
| 11508 | + weather.set_nextweather( calendar::turn ); |
11484 | 11509 | if( move_player ) {
|
11485 | 11510 | place_player( player_pos );
|
11486 | 11511 | }
|
@@ -12711,6 +12736,67 @@ void game::vertical_move( int movez, bool force, bool peeking )
|
12711 | 12736 | cata_event_dispatch::avatar_moves( old_abs_pos, u, here );
|
12712 | 12737 | }
|
12713 | 12738 |
|
| 12739 | +bool game::travel_to_dimension( const std::string &new_prefix ) |
| 12740 | +{ |
| 12741 | + map &here = get_map(); |
| 12742 | + avatar &player = get_avatar(); |
| 12743 | + unload_npcs(); |
| 12744 | + save_dimension_data(); |
| 12745 | + for( monster &critter : all_monsters() ) { |
| 12746 | + despawn_monster( critter ); |
| 12747 | + } |
| 12748 | + if( player.in_vehicle ) { |
| 12749 | + here.unboard_vehicle( player.pos_bub() ); |
| 12750 | + } |
| 12751 | + // Make sure we don't mess up savedata if for some reason maps can't be saved |
| 12752 | + if( !save_maps() ) { |
| 12753 | + return false; |
| 12754 | + } |
| 12755 | + player.save_map_memory(); |
| 12756 | + for( int z = -OVERMAP_DEPTH; z <= OVERMAP_HEIGHT; z++ ) { |
| 12757 | + here.clear_vehicle_list( z ); |
| 12758 | + } |
| 12759 | + here.rebuild_vehicle_level_caches(); |
| 12760 | + // Inputting an empty string to the text input EOC fails |
| 12761 | + // so i'm using 'default' as empty/main dimension |
| 12762 | + if( new_prefix != "default" ) { |
| 12763 | + dimension_prefix = new_prefix; |
| 12764 | + } else { |
| 12765 | + dimension_prefix.clear(); |
| 12766 | + } |
| 12767 | + // Load in data specific to the dimension (like weather) |
| 12768 | + //if( !load_dimension_data() ) { |
| 12769 | + // dimension data file not found/created yet |
| 12770 | + /* handle weather instance switching when I have dimensions with different region settings, |
| 12771 | + right now they're all the same and it's hard to tell if it's working or not. */ |
| 12772 | + // weather.set_nextweather( calendar::turn ); |
| 12773 | + //} |
| 12774 | + // Clear the immediate game area around the player |
| 12775 | + MAPBUFFER.clear(); |
| 12776 | + // hack to prevent crashes from temperature checks |
| 12777 | + // This returns to false in 'on_turn()' so it should be fine? |
| 12778 | + swapping_dimensions = true; |
| 12779 | + // Clear the overmap |
| 12780 | + overmap_buffer.clear(); |
| 12781 | + // load/create new overmap |
| 12782 | + overmap_buffer.get( point_abs_om{} ); |
| 12783 | + // clear map memory from the previous dimension |
| 12784 | + player.clear_map_memory(); |
| 12785 | + // Load map memory in new dimension, if there is any |
| 12786 | + player.load_map_memory(); |
| 12787 | + // Loads submaps and invalidate related caches |
| 12788 | + here.load( tripoint_abs_sm( here.get_abs_sub() ), false ); |
| 12789 | + |
| 12790 | + here.invalidate_visibility_cache(); |
| 12791 | + //without this vehicles only load in after walking around a bit |
| 12792 | + here.reset_vehicles_sm_pos(); |
| 12793 | + load_npcs(); |
| 12794 | + // Handle static monsters |
| 12795 | + here.spawn_monsters( true, true ); |
| 12796 | + update_overmap_seen(); |
| 12797 | + return true; |
| 12798 | +} |
| 12799 | + |
12714 | 12800 | void game::start_hauling( const tripoint_bub_ms &pos )
|
12715 | 12801 | {
|
12716 | 12802 | map &here = get_map();
|
@@ -13690,6 +13776,20 @@ cata_path PATH_INFO::world_base_save_path()
|
13690 | 13776 | return world_generator->active_world->folder_path();
|
13691 | 13777 | }
|
13692 | 13778 |
|
| 13779 | +cata_path PATH_INFO::current_dimension_save_path() |
| 13780 | +{ |
| 13781 | + std::string dimension_prefix = g->get_dimension_prefix(); |
| 13782 | + if( !dimension_prefix.empty() ) { |
| 13783 | + return PATH_INFO::world_base_save_path() / "dimensions" / dimension_prefix; |
| 13784 | + } |
| 13785 | + return PATH_INFO::world_base_save_path(); |
| 13786 | +} |
| 13787 | + |
| 13788 | +cata_path PATH_INFO::current_dimension_player_save_path() |
| 13789 | +{ |
| 13790 | + return PATH_INFO::current_dimension_save_path() / base64_encode( get_avatar().get_save_id() ); |
| 13791 | +} |
| 13792 | + |
13693 | 13793 | void game::shift_destination_preview( const point_rel_ms &delta )
|
13694 | 13794 | {
|
13695 | 13795 | for( tripoint_bub_ms &p : destination_preview ) {
|
|
0 commit comments