Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Player snaps back if teleport fails #72887

Closed
wants to merge 9 commits into from
Closed
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
47 changes: 41 additions & 6 deletions src/game.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11377,8 +11377,13 @@ point game::place_player( const tripoint &dest_loc, bool quick )
return submap_shift;
}

void game::place_player_overmap( const tripoint_abs_omt &om_dest, bool move_player )
void game::place_player_overmap( const tripoint_abs_ms &ms_dest, bool move_player )
{
if( ms_dest == project_to<coords::ms>( u.global_sm_location() - point( HALF_MAPSIZE,
HALF_MAPSIZE ) ) + u.pos() ) {
return; // Already there
}

// if player is teleporting around, they don't bring their horse with them
if( u.is_mounted() ) {
u.remove_effect( effect_riding );
Expand All @@ -11399,20 +11404,50 @@ void game::place_player_overmap( const tripoint_abs_omt &om_dest, bool move_play
m.rebuild_vehicle_level_caches();
m.access_cache( m.get_abs_sub().z() ).map_memory_cache_dec.reset();
m.access_cache( m.get_abs_sub().z() ).map_memory_cache_ter.reset();
// offset because load_map expects the coordinates of the top left corner, but the
// player will be centered in the middle of the map.
// Set this now, if game::place_player fails we'll need it to recover.
const tripoint_abs_sm tele_from = u.global_sm_location();
// The subtraction is to get the reality bubble NW corner from the center position.
const tripoint_abs_sm map_sm_pos =
project_to<coords::sm>( om_dest ) - point( HALF_MAPSIZE, HALF_MAPSIZE );
const tripoint player_pos( u.pos().xy(), map_sm_pos.z() );
project_to<coords::sm>( ms_dest ) - point( HALF_MAPSIZE, HALF_MAPSIZE );
const tripoint_bub_ms player_pos( u.pos_bub().xy(), map_sm_pos.z() );
load_map( map_sm_pos );
load_npcs();
m.spawn_monsters( true ); // Static monsters
update_overmap_seen();
// update weather now as it could be different on the new location
weather.nextweather = calendar::turn;
if( move_player ) {
place_player( player_pos );
place_player( player_pos.raw() );
}
const tripoint_abs_sm tele_to = u.global_sm_location();
if( tele_from != tele_to || !move_player ) {
return;
} // else tele_from == tele_to !!!
// We've failed to teleport for some reason (probably monsters occupying destination squares).
// Let's try to recover gracefully. But also throw a warning, this is bad!
debugmsg( "Failed to place player at destination. If you see this outside of debug teleporting it is a bug." );
update_map( u, ms_dest.z() != tele_from.z() );
// This recursive call safely calls map::load_map() again after making sure everything has been unloaded properly.
// Basically, its only purpose it to reset the z-level to the z-level you teleported *from*. Otherwise, it's redundant after update_map
// Again, translate the reality bubble reference to a mapsquare one.
place_player_overmap( project_to<coords::ms>( tele_from - point( HALF_MAPSIZE,
HALF_MAPSIZE ) ) + player_pos.raw() );
}

void game::place_player_overmap( const tripoint_abs_omt &om_dest, bool move_player )
{
// Project the bubble reference to a submap reference.
tripoint offset = u.pos() - point( 5 * SEEX, 5 * SEEY );

// And then on to an overmap one.
if( abs( u.global_sm_location().x() ) % 2 == 1 ) {
offset.x += SEEX;
}
if( abs( u.global_sm_location().y() ) % 2 == 1 ) {
offset.y += SEEY;
}

place_player_overmap( project_to<coords::ms>( om_dest ) + offset, move_player );
}

bool game::phasing_move( const tripoint &dest_loc, const bool via_ramp )
Expand Down
1 change: 1 addition & 0 deletions src/game.h
Original file line number Diff line number Diff line change
Expand Up @@ -948,6 +948,7 @@ class game
void insert_item( drop_locations &targets );
// Places the player at the specified point; hurts feet, lists items etc.
point place_player( const tripoint &dest, bool quick = false );
void place_player_overmap( const tripoint_abs_ms &ms_dest, bool move_player = true );
void place_player_overmap( const tripoint_abs_omt &om_dest, bool move_player = true );
void perhaps_add_random_npc( bool ignore_spawn_timers_and_rates );
static void display_om_pathfinding_progress( size_t open_set, size_t known_size );
Expand Down
3 changes: 2 additions & 1 deletion tests/water_movement_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,7 @@

// Put us back at 0. We shouldn't have to do this but other tests are
// making assumptions about what z-level they're on.
g->vertical_shift( 0 );
dummy.setpos( test_origin );
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The issue comes from this change. game::vertical_shift sets abs_sub on the map object. And apparently Creature::setpos does not, so the map still thinks it's at z-level -1 when the avatar moves in subsequent tests, which sets the avatar z-level to -1 when game::update_map is called.

}

static const efftype_id effect_winded( "winded" );
Expand Down Expand Up @@ -274,7 +274,7 @@
REQUIRE( swimmer.pos() == left );
REQUIRE( avatar_action::move( swimmer, here, tripoint_east ) );
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Again, this wants an offset like tripoint_east, not a coordinate like left.

} else {
REQUIRE( swimmer.pos() == right );

Check failure on line 277 in tests/water_movement_test.cpp

View workflow job for this annotation

GitHub Actions / Basic Build and Test (Clang 10, Ubuntu, Curses)

(61,60,-2) == (61,60,0)

Check failure on line 277 in tests/water_movement_test.cpp

View workflow job for this annotation

GitHub Actions / Basic Build and Test (Clang 10, Ubuntu, Curses)

(61,60,-2) == (61,60,0)

Check failure on line 277 in tests/water_movement_test.cpp

View workflow job for this annotation

GitHub Actions / Basic Build and Test (Clang 10, Ubuntu, Curses)

(61,60,-2) == (61,60,0)

Check failure on line 277 in tests/water_movement_test.cpp

View workflow job for this annotation

GitHub Actions / Basic Build and Test (Clang 10, Ubuntu, Curses)

(61,60,-2) == (61,60,0)

Check failure on line 277 in tests/water_movement_test.cpp

View workflow job for this annotation

GitHub Actions / Basic Build and Test (Clang 10, Ubuntu, Curses)

(61,60,-2) == (61,60,0)

Check failure on line 277 in tests/water_movement_test.cpp

View workflow job for this annotation

GitHub Actions / Basic Build and Test (Clang 10, Ubuntu, Curses)

(61,60,-2) == (61,60,0)

Check failure on line 277 in tests/water_movement_test.cpp

View workflow job for this annotation

GitHub Actions / Basic Build and Test (Clang 10, Ubuntu, Curses)

(61,60,-2) == (61,60,0)

Check failure on line 277 in tests/water_movement_test.cpp

View workflow job for this annotation

GitHub Actions / Basic Build and Test (Clang 10, Ubuntu, Curses)

(61,60,-2) == (61,60,0)
REQUIRE( avatar_action::move( swimmer, here, tripoint_west ) );
}
++steps;
Expand Down Expand Up @@ -905,6 +905,7 @@

TEST_CASE( "check_swim_move_cost_and_distance_values", "[swimming][slow]" )
{
clear_avatar();
setup_test_lake();

avatar &dummy = get_avatar();
Expand Down
Loading