Skip to content

Commit 39421f6

Browse files
committed
Dimensional travel for vehicles
1 parent b3ea779 commit 39421f6

File tree

11 files changed

+156
-8
lines changed

11 files changed

+156
-8
lines changed

data/json/debug/teleportation.json

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
[
2+
{
3+
"type": "effect_on_condition",
4+
"id": "EOC_PERAMBULATE_VEHICLE",
5+
"//": "Example EOC that shifts a vehicle to the test dimension",
6+
"effect": [
7+
{
8+
"if": { "current_dimension": "" },
9+
"then": { "set_string_var": "test", "target_var": { "u_val": "destination_dimension" } },
10+
"else": { "set_string_var": "", "target_var": { "u_val": "destination_dimension" } }
11+
},
12+
{
13+
"u_travel_to_dimension": { "u_val": "destination_dimension" },
14+
"region_type": { "u_val": "test" },
15+
"take_vehicle": true,
16+
"fail_message": "The Perambulator shivers but does not move.",
17+
"success_message": "In a flash of light the surroundings outside the Perambulator are changed!."
18+
},
19+
{ "u_message": { "u_val": "destination_dimension" } },
20+
{ "if": { "current_dimension": "" }, "then": { "u_message": "home sweet home" } }
21+
]
22+
},
23+
{
24+
"id": "dimensional_perambulator",
25+
"type": "ITEM",
26+
"category": "veh_parts",
27+
"name": { "str": "dimensional perambulator" },
28+
"description": "A perambulator, for perambulating through dimensions",
29+
"weight": "1 kg",
30+
"volume": "5 L",
31+
"material": [ "lc_steel" ],
32+
"symbol": "#",
33+
"color": "dark_gray"
34+
},
35+
{
36+
"id": "dimensional_perambulator",
37+
"type": "vehicle_part",
38+
"name": { "str": "Dimensional Perambulator" },
39+
"item": "dimensional_perambulator",
40+
"location": "center",
41+
"categories": [ "utility" ],
42+
"durability": 100,
43+
"description": "A perambulator, for perambulating through dimensions",
44+
"flags": [ "EOC_ACTIVATION" ],
45+
"activatable_eoc": "EOC_PERAMBULATE_VEHICLE",
46+
"variants": [ { "symbols": "#", "symbols_broken": "X" } ]
47+
},
48+
{
49+
"id": "dimensional_bathyscape",
50+
"//": "Test vehicle for dimensional travel",
51+
"type": "vehicle",
52+
"name": "Sir Pemberton Smythe's Dimensional Bathyscape",
53+
"blueprint": [
54+
[ "---" ],
55+
[ "+#|" ],
56+
[ "---" ]
57+
],
58+
"parts": [
59+
{ "x": -1, "y": -1, "parts": [ "hdframe", "board", "roof" ] },
60+
{ "x": -1, "y": 0, "parts": [ "hdframe", { "part": "tank", "fuel": "gasoline" }, "roof" ] },
61+
{ "x": -1, "y": 1, "parts": [ "hdframe", "engine_v6", "alternator_car", "roof" ] },
62+
{ "x": 0, "y": -1, "parts": [ "hdframe", "door", "roof", "battery_car" ] },
63+
{ "x": 0, "y": 0, "parts": [ "hdframe", "seat", "controls" ] },
64+
{ "x": 0, "y": 1, "parts": [ "hdframe", "roof", "dimensional_perambulator" ] },
65+
{ "x": 1, "y": -1, "parts": [ "hdframe", "board", "roof" ] },
66+
{ "x": 1, "y": 0, "parts": [ "hdframe", "board", "roof" ] },
67+
{ "x": 1, "y": 1, "parts": [ "hdframe", "board", "roof" ] }
68+
]
69+
}
70+
]

data/json/vehicleparts/vp_flags.json

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,11 @@
5454
"type": "json_flag",
5555
"info": "With a seat or saddle, you drive from here. You can 'e'xamine the tile to access the controls, or use the vehicle control key (default '^')."
5656
},
57+
{
58+
"id": "EOC_ACTIVATION",
59+
"type": "json_flag",
60+
"info": "Enables an associated EOC to be triggered from the vehicle control menu."
61+
},
5762
{
5863
"id": "SMART_ENGINE_CONTROLLER",
5964
"type": "json_flag",

src/game.cpp

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11496,7 +11496,8 @@ void game::vertical_move( int movez, bool force, bool peeking )
1149611496

1149711497
bool game::travel_to_dimension( const std::string &new_prefix,
1149811498
const std::string &region_type,
11499-
const std::vector<npc *> &npc_travellers )
11499+
const std::vector<npc *> &npc_travellers,
11500+
vehicle *veh )
1150011501
{
1150111502
map &here = get_map();
1150211503
avatar &player = get_avatar();
@@ -11527,9 +11528,14 @@ bool game::travel_to_dimension( const std::string &new_prefix,
1152711528
for( monster &critter : all_monsters() ) {
1152811529
despawn_monster( critter );
1152911530
}
11531+
bool controlling_vehicle = player.controlling_vehicle;
1153011532
if( player.in_vehicle ) {
1153111533
here.unboard_vehicle( player.pos_bub() );
1153211534
}
11535+
std::unique_ptr<vehicle> vehicle_ref;
11536+
if( veh != nullptr ) {
11537+
vehicle_ref = here.detach_vehicle( veh );
11538+
}
1153311539
// Make sure we don't mess up savedata if for some reason maps can't be saved
1153411540
if( !save_maps() || !save_dimension_data() ) {
1153511541
return false;
@@ -11541,6 +11547,7 @@ bool game::travel_to_dimension( const std::string &new_prefix,
1154111547
here.rebuild_vehicle_level_caches();
1154211548
// Inputting an empty string to the text input EOC fails
1154311549
// so i'm using 'default' as empty/main dimension
11550+
std::string old_prefix = dimension_prefix;
1154411551
if( new_prefix != "default" ) {
1154511552
dimension_prefix = new_prefix;
1154611553
} else {
@@ -11570,15 +11577,26 @@ bool game::travel_to_dimension( const std::string &new_prefix,
1157011577
here.load( tripoint_abs_sm( here.get_abs_sub() ), false );
1157111578

1157211579
here.invalidate_visibility_cache();
11573-
//without this vehicles only load in after walking around a bit
11580+
bool undo_shift = false;
11581+
if( vehicle_ref ) {
11582+
undo_shift = here.place_vehicle( std::move( vehicle_ref ) );
11583+
}
11584+
// Without this vehicles only load in after walking around a bit
1157411585
here.reset_vehicles_sm_pos();
11586+
if( here.veh_at( player.pos_bub() ) ) {
11587+
here.board_vehicle( player.pos_bub(), &player );
11588+
player.controlling_vehicle = controlling_vehicle;
11589+
}
1157511590
load_npcs();
1157611591
// Handle static monsters
1157711592
here.spawn_monsters( true, true );
1157811593
// updates the weather, if the weather settings are different in the new world
1157911594
weather.weather_override = WEATHER_NULL;
1158011595
weather.set_nextweather( calendar::turn );
1158111596
update_overmap_seen();
11597+
if( undo_shift ) {
11598+
travel_to_dimension( old_prefix, region_type, npc_travellers, veh );
11599+
}
1158211600
return true;
1158311601
}
1158411602

src/game.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -333,9 +333,10 @@ class game
333333
* Moves the player to an alternate dimension.
334334
* @param prefix identifies the dimension and its properties.
335335
* @param npc_travellers vector of NPCs that should be brought along when travelling to another dimension
336+
* @param veh pointer to a vehicle to bring along.
336337
*/
337338
bool travel_to_dimension( const std::string &prefix, const std::string &region_type,
338-
const std::vector<npc *> &npc_travellers );
339+
const std::vector<npc *> &npc_travellers, vehicle *veh = nullptr );
339340
/**
340341
* Retrieve the identifier of the current dimension.
341342
* TODO: this should be a dereferencable id that gives properties of the dimension.

src/map.cpp

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -459,6 +459,30 @@ VehicleList map::get_vehicles()
459459
tripoint_bub_ms( SEEX * my_MAPSIZE, SEEY * my_MAPSIZE, OVERMAP_HEIGHT ) );
460460
}
461461

462+
bool map::place_vehicle( std::unique_ptr<vehicle> &&new_vehicle )
463+
{
464+
bool collision = false;
465+
// This works in the dimension shift case specifically because
466+
// the old map origin and the new map origin are the same,
467+
// if that is no longer the case something else will need to happen here.
468+
tripoint_bub_ms vehicle_origin = new_vehicle->pos_bub( *this );
469+
for( std::pair<const point_rel_ms, std::vector<int>> &mount_point : new_vehicle->relative_parts ) {
470+
if( impassable( vehicle_origin + mount_point.first ) ) {
471+
collision = true;
472+
break;
473+
}
474+
}
475+
submap *place_on_submap = get_submap_at_grid( new_vehicle->sm_pos - get_abs_sub().xy() );
476+
if( place_on_submap == nullptr ) {
477+
debugmsg( "Tried to add vehicle at %s but the submap is not loaded",
478+
new_vehicle->sm_pos.to_string() );
479+
} else {
480+
place_on_submap->ensure_nonuniform();
481+
place_on_submap->vehicles.push_back( std::move( new_vehicle ) );
482+
}
483+
return collision;
484+
}
485+
462486
void map::rebuild_vehicle_level_caches()
463487
{
464488
clear_vehicle_level_caches();

src/map.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -761,6 +761,7 @@ class map
761761

762762
// Vehicles: Common to 2D and 3D
763763
VehicleList get_vehicles();
764+
bool place_vehicle( std::unique_ptr<vehicle> &&new_vehicle );
764765
void add_vehicle_to_cache( vehicle * );
765766
void clear_vehicle_point_from_cache( vehicle *veh, const tripoint_bub_ms &pt );
766767
// clears all vehicle level caches

src/npctalk.cpp

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7705,8 +7705,11 @@ talk_effect_fun_t::func f_travel_to_dimension( const JsonObject &jo, std::string
77057705
str_or_var region_type_var;
77067706
optional( jo, false, "region_type", region_type_var, "default" );
77077707

7708+
bool take_vehicle = false;;
7709+
optional( jo, false, "take_vehicle", take_vehicle );
7710+
77087711
return [fail_message, success_message, dimension_prefix, npc_travel_filter,
7709-
npc_travel_radius, region_type_var]( dialogue const & d ) {
7712+
npc_travel_radius, region_type_var, take_vehicle]( dialogue const & d ) {
77107713
Creature *teleporter = d.actor( false )->get_creature();
77117714
if( teleporter ) {
77127715
std::string region_type = region_type_var.evaluate( d );
@@ -7734,8 +7737,17 @@ talk_effect_fun_t::func f_travel_to_dimension( const JsonObject &jo, std::string
77347737
}
77357738
} );
77367739
}
7740+
vehicle *veh = nullptr;
7741+
if( take_vehicle ) {
7742+
const optional_vpart_position vp_here = get_map().veh_at( teleporter->pos_bub() );
7743+
if( !vp_here ) {
7744+
teleporter->add_msg_if_player( fail_message.evaluate( d ) );
7745+
return;
7746+
}
7747+
veh = &vp_here->vehicle();
7748+
}
77377749
// returns False if fail
7738-
if( g->travel_to_dimension( prefix, region_type, travellers ) ) {
7750+
if( g->travel_to_dimension( prefix, region_type, travellers, veh ) ) {
77397751
teleporter->add_msg_if_player( success_message.evaluate( d ) );
77407752
} else {
77417753
teleporter->add_msg_if_player( fail_message.evaluate( d ) );

src/veh_type.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -269,6 +269,7 @@ void vpart_info::load( const JsonObject &jo, const std::string_view src )
269269
optional( jo, was_loaded, "comfort", comfort, 0 );
270270
optional( jo, was_loaded, "floor_bedding_warmth", floor_bedding_warmth, 0_C_delta );
271271
optional( jo, was_loaded, "bonus_fire_warmth_feet", bonus_fire_warmth_feet, 0.6_C_delta );
272+
optional( jo, was_loaded, "activatable_eoc", activatable_eoc );
272273

273274
int enchant_num = 0;
274275
for( JsonValue jv : jo.get_array( "enchantments" ) ) {

src/veh_type.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -334,6 +334,7 @@ class vpart_info
334334
std::optional<vpslot_terrain_transform> transform_terrain_info;
335335
//Enchantments
336336
std::vector<enchantment_id> enchantments;
337+
std::optional<effect_on_condition_id> activatable_eoc;
337338

338339
std::set<std::pair<itype_id, int>> get_pseudo_tools() const;
339340

src/veh_utils.cpp

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -492,9 +492,13 @@ bool veh_menu::query()
492492

493493
chosen._on_submit();
494494

495-
veh.refresh( );
496-
here.invalidate_visibility_cache();
497-
here.invalidate_map_cache( here.get_abs_sub().z() );
495+
// There's probably a better way to detect this?
496+
// If we're swapping dimensions the veh reference has been invalidated.
497+
if( !g->swapping_dimensions ) {
498+
veh.refresh( );
499+
here.invalidate_visibility_cache();
500+
here.invalidate_map_cache( here.get_abs_sub().z() );
501+
}
498502

499503
return chosen._keep_menu_open;
500504
}

0 commit comments

Comments
 (0)