Skip to content

Commit

Permalink
Towing vehicles (#34690)
Browse files Browse the repository at this point in the history
* vehicle patrolling

add UI and sound cues for autopilot, and rework collision detection

remove test code

simple towin WIP

Update src/iuse.cpp

Co-Authored-By: Curtis Merrill <curtis.r.merrill@gmail.com>

increase cable length, and enable serialization/validation of tow data

in-progress - invalidate towing and dump cable part

add handling to clear towing data on part/vehicle destruction or too much distnace

json lint

make recipe use metal cables

transfer tow data when vehicle splits

DEATH TO AUTO

change breaks_into to use new metal recipe

from review: add tow cable to butchery hanging options

from review : change recipe to be HD cable

replace item groups entries for tow_cable with hd_tow_cable

json typo

clang-tidy satisfaction - redundant bool return and differing paramters

add cable to recipe

make towing aware of side it is pulled from for reverse pulling

* add handling for sidepulling and reearpulling without vehicle flipping

* disallow tow move across z-levels

* pointer ->

* stop tower if towed vehicle weight on poor ground results in minimal speed
  • Loading branch information
ZhilkinSerg authored Apr 4, 2020
2 parents 53657b5 + f90ca49 commit c410ebb
Show file tree
Hide file tree
Showing 22 changed files with 662 additions and 40 deletions.
5 changes: 5 additions & 0 deletions data/json/item_actions.json
Original file line number Diff line number Diff line change
Expand Up @@ -309,6 +309,11 @@
"id": "CABLE_ATTACH",
"name": { "str": "Attach" }
},
{
"type": "item_action",
"id": "TOW_ATTACH",
"name": { "str": "Attach" }
},
{
"type": "item_action",
"id": "CAMERA",
Expand Down
2 changes: 2 additions & 0 deletions data/json/itemgroups/Locations_MapExtras/locations.json
Original file line number Diff line number Diff line change
Expand Up @@ -365,6 +365,7 @@
[ "heavy_flashlight", 10 ],
[ "jumper_cable", 20 ],
[ "jumper_cable_heavy", 10 ],
[ "hd_tow_cable", 5 ],
[ "pliers", 10 ],
[ "battery_motorbike", 10 ],
[ "battery_car", 10 ],
Expand Down Expand Up @@ -1321,6 +1322,7 @@
[ "saddle", 8 ],
[ "wheel", 10 ],
[ "wheel_wide", 10 ],
[ "hd_tow_cable", 2 ],
[ "wheel_bicycle", 10 ],
[ "wheel_motorbike", 10 ],
[ "wheel_small", 10 ],
Expand Down
2 changes: 2 additions & 0 deletions data/json/itemgroups/supplies.json
Original file line number Diff line number Diff line change
Expand Up @@ -358,6 +358,7 @@
[ "jumper_cable_heavy", 5 ],
[ "stereo", 25 ],
[ "frame", 20 ],
[ "hd_tow_cable", 5 ],
[ "hdframe", 10 ],
[ "motor", 2 ],
[ "wheel", 10 ],
Expand Down Expand Up @@ -395,6 +396,7 @@
[ "alternator_car", 6 ],
[ "alternator_truck", 6 ],
[ "alternator_bicycle", 4 ],
[ "hd_tow_cable", 1 ],
[ "generator_7500w", 3 ],
[ "storage_battery", 6 ],
[ "motor_oil", 100 ],
Expand Down
1 change: 1 addition & 0 deletions data/json/itemgroups/tools.json
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@
[ "xacto", 40 ],
[ "bucket", 5 ],
[ "jumper_cable", 10 ],
[ "hd_tow_cable", 5 ],
[ "funnel", 50 ],
[ "claw_bar", 2 ],
[ "crowbar", 10 ],
Expand Down
1 change: 1 addition & 0 deletions data/json/itemgroups/vehicles_fuel_related.json
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
{ "item": "duct_tape", "prob": 13, "charges-min": 20, "charges-max": 200 },
[ "screwdriver", 8 ],
[ "screwdriver_set", 2 ],
[ "hd_tow_cable", 5 ],
[ "toolbox", 1 ]
]
},
Expand Down
19 changes: 19 additions & 0 deletions data/json/items/vehicle/cables.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,25 @@
"use_action": "CABLE_ATTACH",
"flags": [ "CABLE_SPOOL" ]
},
{
"type": "TOOL",
"id": "hd_tow_cable",
"name": "heavy duty tow cable",
"description": "An extremely heavy duty tow cable made from thick steel wire. If attached to a vehicle, it could be used to pull another vehicle of any weight.",
"to_hit": -1,
"color": "light_blue",
"symbol": "&",
"material": [ "steel", "plastic" ],
"volume": "3000 ml",
"weight": "24000 g",
"bashing": 6,
"category": "tools",
"price": 80,
"max_charges": 6,
"initial_charges": 6,
"use_action": "TOW_ATTACH",
"flags": [ "CABLE_SPOOL", "TOW_CABLE" ]
},
{
"type": "TOOL",
"id": "jumper_cable_heavy",
Expand Down
13 changes: 13 additions & 0 deletions data/json/recipes/recipe_vehicle.json
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,19 @@
[ [ "rope_superior_short", 2, "LIST" ] ]
]
},
{
"result": "hd_tow_cable",
"type": "recipe",
"category": "CC_OTHER",
"subcategory": "CSC_OTHER_VEHICLE",
"skill_used": "fabrication",
"difficulty": 2,
"time": "480 m",
"autolearn": true,
"qualities": [ { "id": "HAMMER", "level": 1 } ],
"using": [ [ "welding_standard", 8 ] ],
"components": [ [ [ "duct_tape", 50 ] ], [ [ "grip_hook", 1 ] ], [ [ "chain", 8 ] ], [ [ "cable", 10 ] ] ]
},
{
"result": "bike_rack",
"type": "recipe",
Expand Down
16 changes: 16 additions & 0 deletions data/json/vehicleparts/vehicle_parts.json
Original file line number Diff line number Diff line change
Expand Up @@ -2949,6 +2949,22 @@
"flags": [ "NOINSTALL", "UNMOUNT_ON_DAMAGE", "UNMOUNT_ON_MOVE", "POWER_TRANSFER" ],
"breaks_into": [ { "item": "wire", "count": [ 4, 8 ] }, { "item": "plastic_chunk", "count": [ 4, 8 ] } ]
},
{
"type": "vehicle_part",
"id": "hd_tow_cable",
"name": "heavy duty tow cable",
"symbol": "{",
"color": "light_blue",
"broken_symbol": "*",
"broken_color": "dark_gray",
"damage_modifier": 10,
"durability": 120,
"description": "A heavy duty tow cable, if the other end was attached to another vehicle, it could pull it.",
"item": "hd_tow_cable",
"requirements": { "removal": { "time": 500 } },
"flags": [ "NOINSTALL", "UNMOUNT_ON_DAMAGE", "TOW_CABLE" ],
"breaks_into": [ { "item": "scrap", "count": [ 4, 8 ] }, { "item": "grip_hook", "count": 1 }, { "item": "cable", "count": [ 1, 4 ] } ]
},
{
"type": "vehicle_part",
"id": "jumper_cable_debug",
Expand Down
1 change: 1 addition & 0 deletions doc/JSON_FLAGS.md
Original file line number Diff line number Diff line change
Expand Up @@ -391,6 +391,7 @@ Some armor flags, such as `WATCH` and `ALARMCLOCK` are compatible with other ite
- ```TORCH``` Light a torch.
- ```TOURISTMAP``` Learn of local points-of-interest that a tourist would like to visit, and show roads.
- ```TOWEL``` Dry your character using the item as towel.
- ```TOW_ATTACH``` This is a tow cable, activate it to attach it to a vehicle.
- ```TURRET``` Activate a turret.
- ```WASH_ALL_ITEMS``` Wash items with FILTHY flag.
- ```WASH_HARD_ITEMS``` Wash hard items with FILTHY flag.
Expand Down
1 change: 1 addition & 0 deletions src/activity_handlers.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -601,6 +601,7 @@ static void set_up_butchery( player_activity &act, player &u, butcher_type actio
// workshop butchery (full) prequisites
if( action == BUTCHER_FULL ) {
const bool has_rope = u.has_amount( "rope_30", 1 ) || u.has_amount( "rope_makeshift_30", 1 ) ||
u.has_amount( "hd_tow_cable", 1 ) ||
u.has_amount( "vine_30", 1 ) || u.has_amount( "grapnel", 1 );
const bool big_corpse = corpse.size >= MS_MEDIUM;

Expand Down
20 changes: 18 additions & 2 deletions src/game.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1702,8 +1702,8 @@ void game::process_activity()

void game::autopilot_vehicles()
{
for( auto &veh : m.get_vehicles() ) {
auto &v = veh.v;
for( wrapped_vehicle &veh : m.get_vehicles() ) {
vehicle *&v = veh.v;
if( v->is_following ) {
v->drive_to_local_target( g->m.getabs( u.pos() ), true );
} else if( v->is_patrolling ) {
Expand Down Expand Up @@ -1918,6 +1918,21 @@ static void update_faction_api( npc *guy )
}
}

void game::validate_linked_vehicles()
{
for( auto &veh : m.get_vehicles() ) {
vehicle *v = veh.v;
if( v->tow_data.other_towing_point != tripoint_zero ) {
vehicle *other_v = veh_pointer_or_null( m.veh_at( v->tow_data.other_towing_point ) );
if( other_v ) {
// the other vehicle is towing us.
v->tow_data.set_towing( other_v, v );
v->tow_data.other_towing_point = tripoint_zero;
}
}
}
}

void game::validate_mounted_npcs()
{
for( monster &m : all_monsters() ) {
Expand Down Expand Up @@ -2769,6 +2784,7 @@ void game::load( const save_t &name )
validate_npc_followers();
validate_mounted_npcs();
validate_camps();
validate_linked_vehicles();
update_map( u );
for( auto &e : u.inv_dump() ) {
e->set_owner( g->u );
Expand Down
2 changes: 2 additions & 0 deletions src/game.h
Original file line number Diff line number Diff line change
Expand Up @@ -488,6 +488,8 @@ class game
/** validate list of followers to account for overmap buffers */
void validate_npc_followers();
void validate_mounted_npcs();
/** validate towed vehicles so they get linked up again after a load */
void validate_linked_vehicles();
/** validate camps to ensure they are on the overmap list */
void validate_camps();
/** process vehicles that are following the player */
Expand Down
1 change: 1 addition & 0 deletions src/item_factory.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -770,6 +770,7 @@ void Item_factory::init()
add_iuse( "BLECH_BECAUSE_UNCLEAN", &iuse::blech_because_unclean );
add_iuse( "BOLTCUTTERS", &iuse::boltcutters );
add_iuse( "C4", &iuse::c4 );
add_iuse( "TOW_ATTACH", &iuse::tow_attach );
add_iuse( "CABLE_ATTACH", &iuse::cable_attach );
add_iuse( "CAMERA", &iuse::camera );
add_iuse( "CAN_GOO", &iuse::can_goo );
Expand Down
127 changes: 127 additions & 0 deletions src/iuse.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8823,6 +8823,133 @@ int iuse::multicooker( player *p, item *it, bool t, const tripoint &pos )
return 0;
}

int iuse::tow_attach( player *p, item *it, bool, const tripoint & )
{
std::string initial_state = it->get_var( "state", "attach_first" );
if( !p ) {
return 0;
}
const auto set_cable_active = []( player * p, item * it, const std::string & state ) {
it->set_var( "state", state );
it->active = true;
it->process( p, p->pos(), false );
p->moves -= 15;
};
if( initial_state == "attach_first" ) {
const cata::optional<tripoint> posp_ = choose_adjacent(
_( "Attach cable to the vehicle that will do the towing." ) );
if( !posp_ ) {
return 0;
}
const tripoint posp = *posp_;
const optional_vpart_position vp = g->m.veh_at( posp );
if( !vp ) {
p->add_msg_if_player( _( "There's no vehicle there." ) );
return 0;
} else {
vehicle *const source_veh = veh_pointer_or_null( vp );
if( source_veh ) {
if( source_veh->has_tow_attached() || source_veh->is_towed() ||
source_veh->is_towing() ) {
p->add_msg_if_player( _( "That vehicle already has a tow-line attached." ) );
return 0;
}
if( !source_veh->is_external_part( posp ) ) {
p->add_msg_if_player( _( "You can't attach the tow-line to an internal part." ) );
return 0;
}
}
const tripoint &abspos = g->m.getabs( posp );
it->set_var( "source_x", abspos.x );
it->set_var( "source_y", abspos.y );
it->set_var( "source_z", g->get_levz() );
set_cable_active( p, it, "pay_out_cable" );
}
} else {
const auto confirm_source_vehicle = []( player * p, item * it, const bool detach_if_missing ) {
tripoint source_global( it->get_var( "source_x", 0 ),
it->get_var( "source_y", 0 ),
it->get_var( "source_z", 0 ) );
tripoint source_local = g->m.getlocal( source_global );
const optional_vpart_position source_vp = g->m.veh_at( source_local );
vehicle *const source_veh = veh_pointer_or_null( source_vp );
if( detach_if_missing && source_veh == nullptr ) {
if( p->has_item( *it ) ) {
p->add_msg_if_player( m_bad, _( "You notice the cable has come loose!" ) );
}
it->reset_cable( p );
}
return source_vp;
};

const bool paying_out = initial_state == "pay_out_cable";
uilist kmenu;
kmenu.text = _( "Using cable:" );
kmenu.addentry( 0, true, -1, _( "Detach and re-spool the cable" ) );
kmenu.addentry( 1, paying_out, -1, _( "Attach loose end to vehicle" ) );

kmenu.query();
int choice = kmenu.ret;

if( choice < 0 ) {
return 0; // we did nothing.
} else if( choice == 0 ) { // unconnect & respool
it->reset_cable( p );
return 0;
}
const optional_vpart_position source_vp = confirm_source_vehicle( p, it, paying_out );
vehicle *const source_veh = veh_pointer_or_null( source_vp );
if( source_veh == nullptr && paying_out ) {
return 0;
}
const cata::optional<tripoint> vpos_ = choose_adjacent(
_( "Attach cable to vehicle that will be towed." ) );
if( !vpos_ ) {
return 0;
}
const tripoint vpos = *vpos_;

const optional_vpart_position target_vp = g->m.veh_at( vpos );
if( !target_vp ) {
p->add_msg_if_player( _( "There's no vehicle there." ) );
return 0;
} else {
vehicle *const target_veh = &target_vp->vehicle();
if( target_veh && ( target_veh->has_tow_attached() || target_veh->is_towed() ||
target_veh->is_towing() ) ) {
p->add_msg_if_player( _( "That vehicle already has a tow-line attached." ) );
return 0;
}
if( source_veh == target_veh ) {
if( p->has_item( *it ) ) {
p->add_msg_if_player( m_warning, _( "You cannot set a vehicle to tow itself!" ) );
}
return 0;
}
if( !target_veh->is_external_part( vpos ) ) {
p->add_msg_if_player( _( "You can't attach the tow-line to an internal part." ) );
return 0;
}
const vpart_id vpid( it->typeId() );
point vcoords = source_vp->mount();
vehicle_part source_part( vpid, vcoords, item( *it ) );
source_veh->install_part( vcoords, source_part );
vcoords = target_vp->mount();
vehicle_part target_part( vpid, vcoords, item( *it ) );
target_veh->install_part( vcoords, target_part );

if( p->has_item( *it ) ) {
p->add_msg_if_player( m_good, _( "You link up the %1$s and the %2$s." ),
source_veh->name, target_veh->name );
}
source_veh->tow_data.set_towing( source_veh, target_veh );
return 1; // Let the cable be destroyed.
}
}

return 0;
}

int iuse::cable_attach( player *p, item *it, bool, const tripoint & )
{
std::string initial_state = it->get_var( "state", "attach_first" );
Expand Down
1 change: 1 addition & 0 deletions src/iuse.h
Original file line number Diff line number Diff line change
Expand Up @@ -186,6 +186,7 @@ class iuse
int camera( player *, item *, bool, const tripoint & );
int ehandcuffs( player *, item *, bool, const tripoint & );
int foodperson( player *, item *, bool, const tripoint & );
int tow_attach( player *, item *, bool, const tripoint & );
int cable_attach( player *, item *, bool, const tripoint & );
int shavekit( player *, item *, bool, const tripoint & );
int hairkit( player *, item *, bool, const tripoint & );
Expand Down
10 changes: 9 additions & 1 deletion src/map.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -312,7 +312,7 @@ std::unique_ptr<vehicle> map::detach_vehicle( vehicle *veh )
unboard_vehicle( part, passenger );
}
}

veh->invalidate_towing( true );
submap *const current_submap = get_submap_at_grid( veh->sm_pos );
auto &ch = get_cache( z );
for( size_t i = 0; i < current_submap->vehicles.size(); i++ ) {
Expand Down Expand Up @@ -644,6 +644,14 @@ vehicle *map::move_vehicle( vehicle &veh, const tripoint &dp, const tileray &fac
}
}
}
if( veh.is_towing() ) {
veh.do_towing_move();
if( veh.tow_data.get_towed()->tow_cable_too_far() ) {
add_msg( m_info, _( "A towing cable snaps off of the %s." ),
veh.tow_data.get_towed()->disp_name() );
veh.tow_data.get_towed()->invalidate_towing( true );
}
}
// Redraw scene
// But only if the vehicle was seen before or after the move
if( seen || sees_veh( g->u, veh, true ) ) {
Expand Down
Loading

0 comments on commit c410ebb

Please sign in to comment.