Skip to content

Commit

Permalink
feat: drag heavier vehicles (#2840)
Browse files Browse the repository at this point in the history
* feat: drag heavier vehicles

Co-authored-by: anoobindisguise <[email protected]>

* refactor: move variables to be more local

* refactor: extract `make_scraping_noise`

* refactor: extract `get_grabbed_vehicle_movecost`

* refactor: extract `get_vehicle_str_requirement`

---------

Co-authored-by: anoobindisguise <[email protected]>
  • Loading branch information
scarf005 and anoobindisguise authored May 20, 2023
1 parent 937cefe commit f773ca0
Showing 1 changed file with 83 additions and 44 deletions.
127 changes: 83 additions & 44 deletions src/grab.cpp
Original file line number Diff line number Diff line change
@@ -1,12 +1,16 @@
#include "enums.h"
#include "game.h" // IWYU pragma: associated

#include <cstdlib>
#include <algorithm>
#include <numeric>

#include "avatar.h"
#include "character.h"
#include "map.h"
#include "messages.h"
#include "monster.h"
#include "point.h"
#include "sounds.h"
#include "vehicle.h"
#include "vpart_position.h"
Expand All @@ -18,6 +22,68 @@

static const efftype_id effect_harnessed( "harnessed" );

namespace
{
auto make_scraping_noise( const tripoint &pos, const int volume ) -> void
{
sounds::sound( pos, volume, sounds::sound_t::movement,
_( "a scraping noise." ), true, "misc", "scraping" );
}

// vehicle movement: strength check. very strong humans can move about 2,000 kg in a wheelbarrow.
auto base_str_req( vehicle *veh )-> int
{
return veh->total_mass() / 100_kilogram;
}

// determine movecost for terrain touching wheels
auto get_grabbed_vehicle_movecost( vehicle *veh ) -> int
{
const int str_req = base_str_req( veh );
const auto &map = get_map();
const tripoint &vehpos = veh->global_pos3();

static const auto get_wheel_pos = [&]( const int p ) {
return vehpos + veh->part( p ).precalc[0];
};

const auto &wheel_indices = veh->wheelcache;
return std::accumulate( wheel_indices.begin(), wheel_indices.end(), 0,
[&]( const int sum, const int p ) {
const tripoint wheel_pos = get_wheel_pos( p );
const int mapcost = map.move_cost( wheel_pos, veh );
const int movecost = str_req / static_cast<int>( wheel_indices.size() ) * mapcost;

return sum + movecost;
} );
}

//if vehicle has many or only one wheel (shopping cart), it is as if it had four.
auto get_effective_wheels( vehicle *veh ) -> int
{
const auto &wheels = veh->wheelcache;

return ( wheels.size() > 4 || wheels.size() == 1 ) ? 4 : wheels.size();
}

// very strong humans can move about 2,000 kg in a wheelbarrow.
auto get_vehicle_str_requirement( vehicle *veh ) -> int
{
if( !veh->valid_wheel_config() ) {
return base_str_req( veh ) * 10;
}

//if vehicle is rollable we modify str_req based on a function of movecost per wheel.
const int all_movecost = get_grabbed_vehicle_movecost( veh );
// off-road coefficient (always 1.0 on a road, as low as 0.1 off road.)
const float traction = veh->k_traction(
get_map().vehicle_wheel_traction( *veh ) );
return int { 1 + all_movecost / get_effective_wheels( veh ) } / traction;
}

} // namespace


bool game::grabbed_veh_move( const tripoint &dp )
{
const optional_vpart_position grabbed_vehicle_vp = m.veh_at( u.pos() + u.grab_point );
Expand Down Expand Up @@ -77,58 +143,31 @@ bool game::grabbed_veh_move( const tripoint &dp )
// Make sure the mass and pivot point are correct
grabbed_vehicle->invalidate_mass();

//vehicle movement: strength check
int mc = 0;
int str_req = grabbed_vehicle->total_mass() / 25_kilogram; //strength required to move vehicle.

//if vehicle is rollable we modify str_req based on a function of movecost per wheel.

// Vehicle just too big to grab & move; 41-45 lets folks have a bit of a window
// (Roughly 1.1K kg = danger zone; cube vans are about the max)
if( str_req > 45 ) {
add_msg( m_info, _( "The %s is too bulky for you to move by hand." ),
grabbed_vehicle->name );
return true; // No shoving around an RV.
}

const auto &wheel_indices = grabbed_vehicle->wheelcache;
if( grabbed_vehicle->valid_wheel_config() ) {
//determine movecost for terrain touching wheels
const tripoint vehpos = grabbed_vehicle->global_pos3();
for( int p : wheel_indices ) {
const tripoint wheel_pos = vehpos + grabbed_vehicle->part( p ).precalc[0];
const int mapcost = m.move_cost( wheel_pos, grabbed_vehicle );
mc += str_req / wheel_indices.size() * mapcost;
}
//set strength check threshold
//if vehicle has many or only one wheel (shopping cart), it is as if it had four.
if( wheel_indices.size() > 4 || wheel_indices.size() == 1 ) {
str_req = mc / 4 + 1;
} else {
str_req = mc / wheel_indices.size() + 1;
}
} else {
str_req++;
//if vehicle has no wheels str_req make a noise.
if( str_req <= u.get_str() ) {
sounds::sound( grabbed_vehicle->global_pos3(), str_req * 2, sounds::sound_t::movement,
_( "a scraping noise." ), true, "misc", "scraping" );
}
}
//vehicle movement: strength check. very strong humans can move about 2,000 kg in a wheelbarrow.
// int str_req = grabbed_vehicle->total_mass() / 100_kilogram; //strength required to move vehicle.
const int str_req = get_vehicle_str_requirement( grabbed_vehicle );
const int str = u.get_str();
add_msg( m_debug, "str_req: %d", str_req );

//final strength check and outcomes
///\EFFECT_STR determines ability to drag vehicles
if( str_req <= u.get_str() ) {
if( str_req <= str ) {
if( !grabbed_vehicle->valid_wheel_config() ) {
make_scraping_noise( grabbed_vehicle->global_pos3(), str_req * 2 );
}

//calculate exertion factor and movement penalty
///\EFFECT_STR increases speed of dragging vehicles
u.moves -= 100 * str_req / std::max( 1, u.get_str() );
const int ex = dice( 1, 3 ) - 1 + str_req;
if( ex > u.get_str() + 1 ) {
u.moves -= 400 * str_req / std::max( 1, str );
///\EFFECT_STR decreases stamina cost of dragging vehicles
u.mod_stamina( -200 * str_req / std::max( 1, str ) );
const int ex = dice( 1, 6 ) - 1 + str_req;
if( ex > str + 1 ) {
// Pain and movement penalty if exertion exceeds character strength
add_msg( m_bad, _( "You strain yourself to move the %s!" ), grabbed_vehicle->name );
u.moves -= 200;
u.mod_pain( 1 );
} else if( ex >= u.get_str() ) {
} else if( ex >= str ) {
// Movement is slow if exertion nearly equals character strength
add_msg( _( "It takes some time to move the %s." ), grabbed_vehicle->name );
u.moves -= 200;
Expand Down Expand Up @@ -196,7 +235,7 @@ bool game::grabbed_veh_move( const tripoint &dp )
return false;
}

for( int p : wheel_indices ) {
for( int p : grabbed_vehicle->wheelcache ) {
if( one_in( 2 ) ) {
tripoint wheel_p = grabbed_vehicle->global_part_pos3( grabbed_part );
grabbed_vehicle->handle_trap( wheel_p, p );
Expand Down

0 comments on commit f773ca0

Please sign in to comment.