Skip to content

Commit

Permalink
Merge pull request #65414 from irwiss/tidy-vehicle-funcs
Browse files Browse the repository at this point in the history
Refactor index_of_part, tidy vehicle functions
  • Loading branch information
dseguin authored May 2, 2023
2 parents c9db418 + 959332a commit 775f16e
Show file tree
Hide file tree
Showing 9 changed files with 106 additions and 160 deletions.
2 changes: 1 addition & 1 deletion src/game.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5621,7 +5621,7 @@ void game::control_vehicle()
const bool controls_ok = controls_idx >= 0; // controls available to "drive"
const bool reins_ok = reins_idx >= 0 // reins + animal available to "drive"
&& veh->has_engine_type( fuel_type_animal, false )
&& veh->has_harnessed_animal();
&& veh->get_harnessed_animal();
if( veh->player_in_control( u ) ) {
// player already "driving" - offer ways to leave
if( controls_ok ) {
Expand Down
15 changes: 5 additions & 10 deletions src/grab.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,6 @@
#include "vpart_position.h"
#include "vpart_range.h"

static const efftype_id effect_harnessed( "harnessed" );

bool game::grabbed_veh_move( const tripoint &dp )
{
const optional_vpart_position grabbed_vehicle_vp = m.veh_at( u.pos() + u.grab_point );
Expand All @@ -32,14 +30,11 @@ bool game::grabbed_veh_move( const tripoint &dp )
return false;
}
const int grabbed_part = grabbed_vehicle_vp->part_index();
for( const vpart_reference &vpr : grabbed_vehicle->get_all_parts() ) {
monster *mon = grabbed_vehicle->get_monster( vpr.part_index() );
if( mon != nullptr && mon->has_effect( effect_harnessed ) ) {
add_msg( m_info, _( "You cannot move this vehicle whilst your %s is harnessed!" ),
mon->get_name() );
u.grab( object_type::NONE );
return false;
}
if( monster *mon = grabbed_vehicle->get_harnessed_animal() ) {
add_msg( m_info, _( "You cannot move this vehicle whilst your %s is harnessed!" ),
mon->get_name() );
u.grab( object_type::NONE );
return false;
}
const vehicle *veh_under_player = veh_pointer_or_null( m.veh_at( u.pos() ) );
if( grabbed_vehicle == veh_under_player ) {
Expand Down
2 changes: 1 addition & 1 deletion src/handle_action.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -469,7 +469,7 @@ static void pldrive( const tripoint &p )
const bool has_animal_controls = veh->part_with_feature( vp.mount, "CONTROL_ANIMAL", true ) >= 0;
const bool has_controls = veh->part_with_feature( vp.mount, "CONTROLS", true ) >= 0;
const bool has_animal = veh->has_engine_type( fuel_type_animal, false ) &&
veh->has_harnessed_animal();
veh->get_harnessed_animal();
if( !has_controls && !has_animal_controls ) {
add_msg( m_info, _( "You can't drive the vehicle from here. You need controls!" ) );
player_character.controlling_vehicle = false;
Expand Down
30 changes: 16 additions & 14 deletions src/monmove.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -894,20 +894,22 @@ void monster::move()
if( friendly > 0 ) {
--friendly;
}

// don't move if a passenger in a moving vehicle
optional_vpart_position vp = here.veh_at( pos() );
bool harness_part = static_cast<bool>( here.veh_at( pos() ).part_with_feature( "ANIMAL_CTRL",
true ) );
if( vp && ( ( friendly != 0 && vp->vehicle().is_moving() &&
vp->vehicle().get_monster( vp->part_index() ) ) ||
// Don't move if harnessed, even if vehicle is stationary
has_effect( effect_harnessed ) ) ) {
moves = 0;
return;
// If harnessed monster finds itself moved from the harness point, the harness probably broke!
} else if( !harness_part && has_effect( effect_harnessed ) ) {
remove_effect( effect_harnessed );
const optional_vpart_position ovp = here.veh_at( pos() );
if( has_effect( effect_harnessed ) ) {
if( !ovp.part_with_feature( "ANIMAL_CTRL", true ) ) {
remove_effect( effect_harnessed ); // the harness part probably broke
} else {
moves = 0;
return; // don't move if harnessed
}
}
const std::optional<vpart_reference> vp_boardable = ovp.part_with_feature( "BOARDABLE", true );
if( vp_boardable && friendly != 0 ) {
const vehicle &veh = vp_boardable->vehicle();
if( veh.is_moving() && veh.get_monster( vp_boardable->part_index() ) ) {
moves = 0;
return; // don't move if friendly and passenger in a moving vehicle
}
}
// Set attitude to attitude to our current target
monster_attitude current_attitude = attitude( nullptr );
Expand Down
11 changes: 11 additions & 0 deletions src/veh_type.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,8 @@ class npc;

static const ammotype ammo_battery( "battery" );

static const itype_id fuel_type_animal( "animal" );

static const itype_id itype_null( "null" );

static const quality_id qual_JACK( "JACK" );
Expand Down Expand Up @@ -1000,6 +1002,15 @@ void vpart_info::check()
if( part.has_flag( VPFLAG_ENABLED_DRAINS_EPOWER ) && part.epower == 0_W ) {
debugmsg( "%s is set to drain epower, but has epower == 0", part.id.c_str() );
}
if( part.has_flag( VPFLAG_ENGINE ) ) {
if( part.power != 0_W && part.fuel_type == fuel_type_animal ) {
debugmsg( "engine part '%s' powered by '%s' can't define non-zero 'power'",
part.id.c_str(), part.fuel_type.str() );
} else if( part.power == 0_W && part.fuel_type != fuel_type_animal ) {
debugmsg( "engine part '%s' powered by '%s' must define non zero 'power'",
part.id.c_str(), part.fuel_type.str() );
}
}
// Parts with non-zero epower must have a flag that affects epower usage
static const std::vector<std::string> handled = {{
"ENABLED_DRAINS_EPOWER", "SECURITY", "ENGINE",
Expand Down
3 changes: 0 additions & 3 deletions src/veh_type.h
Original file line number Diff line number Diff line change
Expand Up @@ -493,9 +493,6 @@ class vpart_info
int z_order = 0;
// Display order in vehicle interact display
int list_order = 0;

/** Legacy parts don't specify installation requirements */
bool legacy = true;
};

struct vehicle_item_spawn {
Expand Down
146 changes: 55 additions & 91 deletions src/vehicle.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -218,7 +218,7 @@ bool vehicle::player_in_control( const Character &p ) const
if( vp && &vp->vehicle() == this &&
p.controlling_vehicle &&
( ( part_with_feature( vp->mount(), "CONTROL_ANIMAL", true ) >= 0 &&
has_engine_type( fuel_type_animal, false ) && has_harnessed_animal() ) ||
has_engine_type( fuel_type_animal, false ) && get_harnessed_animal() ) ||
( part_with_feature( vp->part_index(), VPFLAG_CONTROLS, false ) >= 0 ) )
) {
return true;
Expand Down Expand Up @@ -1011,43 +1011,32 @@ const vpart_info &vehicle::part_info( int index, bool include_removed ) const
units::power vehicle::part_vpower_w( const vehicle_part &vp, const bool at_full_hp ) const
{
const vpart_info &vpi = vp.info();
const int vp_index = index_of_part( &vp );
units::power pwr = vpi.power;
if( vpi.has_flag( VPFLAG_ENGINE ) ) {
if( pwr == 0_W ) {
pwr = vp.base.engine_displacement() * 373_W;
}
if( vpi.fuel_type == fuel_type_animal ) {
monster *mon = get_monster( index_of_part( &vp ) );
if( mon != nullptr && mon->has_effect( effect_harnessed ) ) {
// An animal that can carry twice as much weight, can pull a cart twice as hard.
pwr = units::from_watt( mon->get_speed() * ( mon->get_size() - 1 ) * 3
* ( mon->get_mountable_weight_ratio() * 5 ) );
} else {
pwr = 0_W;
}
}
// Weary multiplier
const float weary_mult = get_player_character().exertion_adjusted_move_multiplier();
///\EFFECT_STR increases power produced for MUSCLE_* vehicles
pwr += units::from_watt( get_player_character().str_cur - 8 ) * vpi.engine_muscle_power_factor() *
weary_mult;
/// wind-powered vehicles have differing power depending on wind direction
if( vpi.fuel_type == fuel_type_wind ) {
weather_manager &weather = get_weather();
int windpower = weather.windspeed;
rl_vec2d windvec;
double raddir = ( ( weather.winddirection + 180 ) % 360 ) * ( M_PI / 180 );
windvec = windvec.normalized();
windvec.y = -std::cos( raddir );
windvec.x = std::sin( raddir );
rl_vec2d fv = face_vec();
double dot = windvec.dot_product( fv );
if( dot <= 0 ) {
dot = std::min( -0.1, dot );
} else {
dot = std::max( 0.1, dot );
}
units::power windeffectint = units::from_watt( ( windpower * dot ) * 200 );
int factor = 0;
if( const monster *mon = get_monster( vp_index ); mon && mon->has_effect( effect_harnessed ) ) {
factor += mon->get_size() - 1;
factor *= mon->get_speed();
factor *= mon->get_mountable_weight_ratio();
}
pwr = 15_W * factor;
} else if( vpi.fuel_type == fuel_type_muscle ) {
if( const Character *muscle_user = get_passenger( vp_index ) ) {
///\EFFECT_STR increases power produced for MUSCLE_* vehicles
const float muscle_multiplier = muscle_user->str_cur - 8;
const float weary_multiplier = muscle_user->exertion_adjusted_move_multiplier();
const float engine_multiplier = vpi.engine_muscle_power_factor();
pwr += units::from_watt( muscle_multiplier * weary_multiplier * engine_multiplier );
}
} else if( vpi.fuel_type == fuel_type_wind ) {
/// wind-powered vehicles have differing power depending on wind direction
const weather_manager &weather = get_weather();
const double raddir = ( ( weather.winddirection + 180 ) % 360 ) * ( M_PI / 180 );
const rl_vec2d windvec( std::sin( raddir ), -std::cos( raddir ) );
const double dot = windvec.dot_product( face_vec() );
const units::power windeffectint = units::from_watt( weather.windspeed * dot * 200 );
pwr = std::max( 1_W, pwr + windeffectint );
}
}
Expand Down Expand Up @@ -2852,10 +2841,8 @@ std::vector<std::vector<int>> vehicle::find_lines_of_parts(
std::vector<int> x_parts;
std::vector<int> y_parts;

if( parts[part].is_fake ) {
// start from the real part, otherwise it fails in certain orientations
part = parts[part].fake_part_to;
}
// start from the real part, otherwise it fails in certain orientations
part = get_non_fake_part( part );

vpart_id part_id = part_info( part ).get_id();
// create vectors of parts on the same X or Y axis
Expand Down Expand Up @@ -2961,25 +2948,14 @@ int vehicle::part_at( const point &dp ) const
return -1;
}

/**
* Given a vehicle part which is inside of this vehicle, returns the index of
* that part. This exists solely because activities relating to vehicle editing
* require the index of the vehicle part to be passed around.
* @param part The part to find.
* @param check_removed Check whether this part can be removed
* @return The part index, -1 if it is not part of this vehicle.
*/
int vehicle::index_of_part( const vehicle_part *const part, const bool check_removed ) const
int vehicle::index_of_part( const vehicle_part *part, bool include_removed ) const
{
if( part != nullptr ) {
for( const vpart_reference &vp : get_all_parts() ) {
const vehicle_part &next_part = vp.part();
if( !check_removed && next_part.removed ) {
continue;
}
if( part->id == next_part.id && part->mount == vp.mount() ) {
return vp.part_index();
}
if( !part || ( !include_removed && part->removed ) ) {
return -1;
}
for( size_t i = 0; i < parts.size(); i++ ) {
if( &parts[i] == part ) {
return static_cast<int>( i );
}
}
return -1;
Expand Down Expand Up @@ -4485,21 +4461,18 @@ float vehicle::steering_effectiveness() const
if( steering.empty() ) {
return -1.0f; // No steering installed
}
// If the only steering part is an animal harness, with no animal in, it
// is not steerable.
const vehicle_part &vp = parts[ steering[0] ];
if( steering.size() == 1 && vp.info().fuel_type == fuel_type_animal ) {
monster *mon = get_monster( steering[0] );
if( mon == nullptr || !mon->has_effect( effect_harnessed ) ) {
return -2.0f;
}
// no steering if only steering part is animal harness without animal in it
const vehicle_part &vp = parts[steering[0]];
if( steering.size() == 1 && vp.info().fuel_type == fuel_type_animal && !get_harnessed_animal() ) {
return -2.0f;
}
// For now, you just need one wheel working for 100% effective steering.
// TODO: return something less than 1.0 if the steering isn't so good
// (unbalanced, long wheelbase, back-heavy vehicle with front wheel steering,
// etc)
for( int p : steering ) {
if( parts[ p ].is_available() ) {
for( const int p : steering ) {
const vehicle_part &vp = parts[p];
if( vp.is_available() ) {
return 1.0f;
}
}
Expand Down Expand Up @@ -5747,25 +5720,20 @@ void vehicle::gain_moves()
}
}

void vehicle::dump_items_from_part( const size_t index )
{
map &here = get_map();
vehicle_part &vp = parts[ index ];
for( item &e : vp.items ) {
here.add_item_or_charges( global_part_pos3( vp ), e );
}
vp.items.clear();
}

bool vehicle::decrement_summon_timer()
{
if( !summon_time_limit ) {
return false;
}
if( *summon_time_limit <= 0_turns ) {
for( const vpart_reference &vp : get_all_parts() ) {
const size_t p = vp.part_index();
dump_items_from_part( p );
map &here = get_map();
for( const vpart_reference &vpr : get_all_parts() ) {
vehicle_part &vp = vpr.part();
const tripoint_bub_ms pos = bub_part_pos( vp );
for( item &it : vp.items ) {
here.add_item_or_charges( pos, it );
}
vp.items.clear();
}
add_msg_if_player_sees( global_pos3(), m_info, _( "Your %s winks out of existence." ), name );
get_map().destroy_vehicle( this );
Expand Down Expand Up @@ -7654,19 +7622,15 @@ const vehicle_part &vehicle::part( int part_num ) const
return parts[part_num];
}

int vehicle::get_non_fake_part( const int part_num )
int vehicle::get_non_fake_part( const int part_num ) const
{
if( part_num != -1 && part_num < part_count() ) {
const vehicle_part &vp = parts.at( part_num );
if( vp.is_fake ) {
return vp.fake_part_to;
} else {
return part_num;
}
if( part_num < 0 || part_num >= part_count() ) {
debugmsg( "get_non_fake_part(%d) returning -1 on '%s', which has %d parts.",
part_num, disp_name(), parts.size() );
return -1;
}
debugmsg( "Returning -1 for get_non_fake_part on part_num %d on %s, which has %d parts.", part_num,
disp_name(), parts.size() );
return -1;
const vehicle_part &vp = parts[part_num];
return vp.is_fake ? vp.fake_part_to : part_num;
}

vehicle_part_range vehicle::get_all_parts() const
Expand Down
12 changes: 5 additions & 7 deletions src/vehicle.h
Original file line number Diff line number Diff line change
Expand Up @@ -1220,8 +1220,9 @@ class vehicle
bool below_roof = true, bool roof = true ) const;
int roof_at_part( int p ) const;

// Given a part, finds its index in the vehicle
int index_of_part( const vehicle_part *part, bool check_removed = false ) const;
// Finds index of a given vehicle_part in parts vector, compared by address
// @return index or -1 if part is nullptr, not found or removed and include_removed is false.
int index_of_part( const vehicle_part *part, bool include_removed = false ) const;

// get symbol for map
char part_sym( int p, bool exact = false, bool include_fake = true ) const;
Expand Down Expand Up @@ -1703,7 +1704,6 @@ class vehicle
vehicle_stack get_items( int part );
std::vector<item> &get_tools( vehicle_part &vp );
const std::vector<item> &get_tools( const vehicle_part &vp ) const;
void dump_items_from_part( size_t index );

// Generates starting items in the car, should only be called when placed on the map
void place_spawn_items();
Expand Down Expand Up @@ -1845,8 +1845,6 @@ class vehicle
// @returns true if succeeded
bool restore_folded_parts( const item &it );

//handles locked vehicles interaction
bool interact_vehicle_locked();
//true if an alarm part is installed on the vehicle
bool has_security_working() const;
/**
Expand Down Expand Up @@ -1890,7 +1888,7 @@ class vehicle
//true if an engine exists with specified type
//If enabled true, this engine must be enabled to return true
bool has_engine_type( const itype_id &ft, bool enabled ) const;
bool has_harnessed_animal() const;
monster *get_harnessed_animal() const;
//true if an engine exists without the specified type
//If enabled true, this engine must be enabled to return true
bool has_engine_type_not( const itype_id &ft, bool enabled ) const;
Expand Down Expand Up @@ -2008,7 +2006,7 @@ class vehicle
vehicle_part &part( int part_num );
const vehicle_part &part( int part_num ) const;
// get the parent part of a fake part or return part_num otherwise
int get_non_fake_part( int part_num );
int get_non_fake_part( int part_num ) const;
// Updates active state on all fake_mounts based on whether they can fill a gap
// map.cpp calls this in displace_vehicle
void update_active_fakes();
Expand Down
Loading

0 comments on commit 775f16e

Please sign in to comment.