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

Misc bugfixes from DDA 6 #316

Merged
merged 12 commits into from
Jan 17, 2021
41 changes: 25 additions & 16 deletions src/character.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9105,26 +9105,35 @@ int Character::floor_bedding_warmth( const tripoint &pos )

int Character::floor_item_warmth( const tripoint &pos )
{
if( !g->m.has_items( pos ) ) {
return 0;
}

int item_warmth = 0;
// Search the floor for items
const auto floor_item = g->m.i_at( pos );
for( const auto &elem : floor_item ) {
if( !elem.is_armor() ) {
continue;

const auto warm = [&item_warmth]( const auto & stack ) {
for( const item &elem : stack ) {
if( !elem.is_armor() ) {
continue;
}
// Items that are big enough and covers the torso are used to keep warm.
// Smaller items don't do as good a job
if( elem.volume() > 250_ml &&
( elem.covers( bp_torso ) || elem.covers( bp_leg_l ) ||
elem.covers( bp_leg_r ) ) ) {
item_warmth += 60 * elem.get_warmth() * elem.volume() / 2500_ml;
}
}
// Items that are big enough and covers the torso are used to keep warm.
// Smaller items don't do as good a job
if( elem.volume() > 250_ml &&
( elem.covers( bp_torso ) || elem.covers( bp_leg_l ) ||
elem.covers( bp_leg_r ) ) ) {
item_warmth += 60 * elem.get_warmth() * elem.volume() / 2500_ml;
};

if( !!g->m.veh_at( pos ) ) {
Copy link
Member

Choose a reason for hiding this comment

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

This could probably be skipped.
The items under the vehicle are still reachable anyway.

if( const cata::optional<vpart_reference> vp = g->m.veh_at( pos ).part_with_feature( VPFLAG_CARGO,
false ) ) {
vehicle *const veh = &vp->vehicle();
const int cargo = vp->part_index();
vehicle_stack vehicle_items = veh->get_items( cargo );
warm( vehicle_items );
}
return item_warmth;
}

map_stack floor_items = g->m.i_at( pos );
warm( floor_items );
return item_warmth;
}

Expand Down
69 changes: 60 additions & 9 deletions src/computer_session.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,8 @@ static const mtype_id mon_secubot( "mon_secubot" );

static const std::string flag_CONSOLE( "CONSOLE" );

static const itype_id itype_sarcophagus_access_code( "sarcophagus_access_code" );

static catacurses::window init_window()
{
const int width = FULL_SCREEN_WIDTH;
Expand Down Expand Up @@ -931,19 +933,68 @@ void computer_session::action_srcf_seal()

void computer_session::action_srcf_elevator()
{
if( !g->u.has_amount( "sarcophagus_access_code", 1 ) ) {
print_error( _( "Access code required!" ) );
} else {
g->u.use_amount( "sarcophagus_access_code", 1 );
Character &player_character = g->u;
map &here = g->m;
tripoint surface_elevator;
tripoint underground_elevator;
bool is_surface_elevator_on = false;
bool is_surface_elevator_exist = false;
bool is_underground_elevator_on = false;
bool is_underground_elevator_exist = false;

for( const tripoint &p : here.points_on_zlevel( 0 ) ) {
if( here.ter( p ) == t_elevator_control_off || here.ter( p ) == t_elevator_control ) {
surface_elevator = p;
is_surface_elevator_on = here.ter( p ) == t_elevator_control;
is_surface_elevator_exist = true;
}
}
for( const tripoint &p : here.points_on_zlevel( -2 ) ) {
if( here.ter( p ) == t_elevator_control_off || here.ter( p ) == t_elevator_control ) {
underground_elevator = p;
is_underground_elevator_on = here.ter( p ) == t_elevator_control;
is_underground_elevator_exist = true;
}
}

//If some are destroyed
if( !is_surface_elevator_exist || !is_underground_elevator_exist ) {
reset_terminal();
print_error(
_( "\nElevator control network unreachable!\n\n" ) );
}

//If both are disabled try to enable
else if( !is_surface_elevator_on && !is_underground_elevator_on ) {
if( !player_character.has_amount( itype_sarcophagus_access_code, 1 ) ) {
print_error( _( "Access code required!\n\n" ) );
} else {
player_character.use_amount( itype_sarcophagus_access_code, 1 );
here.ter_set( surface_elevator, t_elevator_control );
is_surface_elevator_on = true;
here.ter_set( underground_elevator, t_elevator_control );
is_underground_elevator_on = true;
}
}

//If only one is enabled, enable the other one. Fix for before this change
else if( is_surface_elevator_on && !is_underground_elevator_on && is_underground_elevator_exist ) {
here.ter_set( underground_elevator, t_elevator_control );
is_underground_elevator_on = true;
}

else if( is_underground_elevator_on && !is_surface_elevator_on && is_surface_elevator_exist ) {
here.ter_set( surface_elevator, t_elevator_control );
is_surface_elevator_on = true;
}

//If the elevator is working
if( is_surface_elevator_on && is_underground_elevator_on ) {
reset_terminal();
print_line(
_( "\nPower: Backup Only\nRadiation Level: Very Dangerous\nOperational: Overridden\n\n" ) );
for( const tripoint &p : g->m.points_on_zlevel() ) {
if( g->m.ter( p ) == t_elevator_control_off ) {
g->m.ter_set( p, t_elevator_control );
}
}
}

query_any( _( "Press any key…" ) );
}

Expand Down
6 changes: 4 additions & 2 deletions src/game.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1734,6 +1734,7 @@ bool game::cancel_activity_query( const std::string &text )
}
if( query_yn( "%s %s", text, u.activity.get_stop_phrase() ) ) {
u.cancel_activity();
u.clear_destination();
u.resume_backlog_activity();
return true;
}
Expand Down Expand Up @@ -4879,10 +4880,11 @@ monster *game::place_critter_around( const mtype_id &id, const tripoint &center,

monster *game::place_critter_around( const shared_ptr_fast<monster> &mon,
const tripoint &center,
const int radius )
const int radius,
bool forced )
{
cata::optional<tripoint> where;
if( can_place_monster( *mon, center ) ) {
if( forced || can_place_monster( *mon, center ) ) {
where = center;
}

Expand Down
2 changes: 1 addition & 1 deletion src/game.h
Original file line number Diff line number Diff line change
Expand Up @@ -338,7 +338,7 @@ class game
monster *place_critter_at( const shared_ptr_fast<monster> &mon, const tripoint &p );
monster *place_critter_around( const mtype_id &id, const tripoint &center, int radius );
monster *place_critter_around( const shared_ptr_fast<monster> &mon, const tripoint &center,
int radius );
int radius, bool forced = false );
monster *place_critter_within( const mtype_id &id, const tripoint_range &range );
monster *place_critter_within( const shared_ptr_fast<monster> &mon,
const tripoint_range &range );
Expand Down
9 changes: 7 additions & 2 deletions src/gates.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -282,8 +282,13 @@ void doors::close_door( map &m, Character &who, const tripoint &closep )
if( !veh->handle_potential_theft( dynamic_cast<player &>( g->u ) ) ) {
return;
}
veh->close( closable );
didit = true;
Character *ch = who.as_character();
if( ch && veh->can_close( closable, *ch ) ) {
veh->close( closable );
//~ %1$s - vehicle name, %2$s - part name
who.add_msg_if_player( _( "You close the %1$s's %2$s." ), veh->name, veh->parts[closable].name() );
didit = true;
}
} else if( inside_closable >= 0 ) {
who.add_msg_if_player( m_info, _( "That %s can only be closed from the inside." ),
veh->parts[inside_closable].name() );
Expand Down
4 changes: 3 additions & 1 deletion src/magic_spell_effect.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -435,7 +435,9 @@ static void damage_targets( const spell &sp, Creature &caster,
cr->deal_projectile_attack( &caster, atk, true );
} else if( sp.damage() < 0 ) {
sp.heal( target );
add_msg( m_good, _( "%s wounds are closing up!" ), cr->disp_name( true ) );
if( g->u.sees( cr->pos() ) ) {
add_msg( m_good, _( "%s wounds are closing up!" ), cr->disp_name( true ) );
}
Copy link
Member

Choose a reason for hiding this comment

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

Not caused here, but it seems that it still prints the message even if there are no wounds to close up.

}
}
}
Expand Down
4 changes: 1 addition & 3 deletions src/monattack.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1634,9 +1634,7 @@ bool mattack::fungus( monster *z )
// TODO: Infect NPCs?
// It takes a while
z->moves -= 200;
if( g->u.has_trait( trait_THRESH_MYCUS ) ) {
z->friendly = 100;
}

//~ the sound of a fungus releasing spores
sounds::sound( z->pos(), 10, sounds::sound_t::combat, _( "Pouf!" ), false, "misc", "puff" );
if( g->u.sees( *z ) ) {
Expand Down
7 changes: 4 additions & 3 deletions src/output.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,7 @@ std::string remove_color_tags( const std::string &s )
std::vector<size_t> tag_positions = get_tag_positions( s );
size_t next_pos = 0;

if( tag_positions.size() > 1 ) {
if( !tag_positions.empty() ) {
for( size_t tag_position : tag_positions ) {
ret += s.substr( next_pos, tag_position - next_pos );
next_pos = s.find( ">", tag_position, 1 ) + 1;
Expand Down Expand Up @@ -240,8 +240,9 @@ std::string trim_by_length( const std::string &text, int width )
iLength += iTempLen;

if( iLength > width ) {
sTempText = sTempText.substr( 0, cursorx_to_position( sTempText.c_str(),
iTempLen - ( iLength - width ) - 1, nullptr, -1 ) ) + "\u2026";
int pos = 0;
cursorx_to_position( sTempText.c_str(), iTempLen - ( iLength - width ) - 1, &pos, -1 );
sTempText = sTempText.substr( 0, pos ) + "\u2026";
}

sText += sColor + sTempText;
Expand Down
4 changes: 2 additions & 2 deletions src/overmapbuffer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1418,8 +1418,8 @@ void overmapbuffer::spawn_monster( const tripoint &p )
// The monster position must be local to the main map when added to the game
const tripoint local = tripoint( g->m.getlocal( ms ), p.z );
assert( g->m.inbounds( local ) );
monster *const placed = g->place_critter_at( make_shared_fast<monster>( this_monster ),
local );
monster *const placed = g->place_critter_around( make_shared_fast<monster>( this_monster ),
local, 0, true );
if( placed ) {
placed->on_load();
}
Expand Down
3 changes: 2 additions & 1 deletion src/savegame_json.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1014,7 +1014,8 @@ void avatar::load( const JsonObject &data )
if( data.read( "profession", prof_ident ) && string_id<profession>( prof_ident ).is_valid() ) {
prof = &string_id<profession>( prof_ident ).obj();
} else {
debugmsg( "Tried to use non-existent profession '%s'", prof_ident.c_str() );
//We are likely an older profession which has since been removed so just set to default. This is only cosmetic after game start.
prof = profession::generic();
}

data.read( "controlling_vehicle", controlling_vehicle );
Expand Down
15 changes: 9 additions & 6 deletions src/turret.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -577,6 +577,7 @@ int vehicle::automatic_fire_turret( vehicle_part &pt )
}

const bool u_see = g->u.sees( pos );
const bool u_hear = !g->u.is_deaf();
// The current target of the turret.
auto &target = pt.target;
if( target.first == target.second ) {
Expand All @@ -593,16 +594,18 @@ int vehicle::automatic_fire_turret( vehicle_part &pt )
if( auto_target == nullptr ) {
if( boo_hoo ) {
cpu.name = string_format( pgettext( "vehicle turret", "The %s" ), pt.name() );
if( u_see ) {
// check if the player can see or hear then print chooses a message accordingly
if( u_see && u_hear ) {
add_msg( m_warning, ngettext( "%s points in your direction and emits an IFF warning beep.",
"%s points in your direction and emits %d annoyed sounding beeps.",
boo_hoo ),
cpu.name, boo_hoo );
} else {
add_msg( m_warning, ngettext( "%s emits an IFF warning beep.",
"%s emits %d annoyed sounding beeps.",
boo_hoo ),
cpu.name, boo_hoo );
} else if( u_hear ) {
add_msg( m_warning, ngettext( "You hear a warning beep.",
"You hear %d annoyed sounding beeps.",
boo_hoo ), boo_hoo );
} else if( u_see ) {
add_msg( m_warning, _( "%s points in your direction." ), cpu.name );
}
}
return shots;
Expand Down
2 changes: 2 additions & 0 deletions src/vehicle.h
Original file line number Diff line number Diff line change
Expand Up @@ -1581,6 +1581,8 @@ class vehicle
// returns whether the door is open or not
bool is_open( int part_index ) const;

bool can_close( int part_index, Character &who );

// Consists only of parts with the FOLDABLE tag.
bool is_foldable() const;
// Restore parts of a folded vehicle.
Expand Down
21 changes: 21 additions & 0 deletions src/vehicle_use.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1486,6 +1486,27 @@ bool vehicle::is_open( int part_index ) const
return parts[part_index].open;
}

bool vehicle::can_close( int part_index, Character &who )
{
for( auto const &vec : find_lines_of_parts( part_index, "OPENABLE" ) ) {
for( auto const &partID : vec ) {
const Creature *const mon = g->critter_at( global_part_pos3( parts[partID] ) );
if( mon ) {
if( mon->is_player() ) {
who.add_msg_if_player( m_info, _( "There's some buffoon in the way!" ) );
} else if( mon->is_monster() ) {
// TODO: Houseflies, mosquitoes, etc shouldn't count
Copy link
Member

Choose a reason for hiding this comment

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

We won't have those.

who.add_msg_if_player( m_info, _( "The %s is in the way!" ), mon->get_name() );
} else {
who.add_msg_if_player( m_info, _( "%s is in the way!" ), mon->disp_name() );
}
return false;
}
}
}
return true;
}

void vehicle::open_all_at( int p )
{
std::vector<int> parts_here = parts_at_relative( parts[p].mount, true );
Expand Down
40 changes: 40 additions & 0 deletions tests/string_test.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
#include "catch/catch.hpp"

#include <string>

#include "output.h"

static void test_remove_color_tags( const std::string &original, const std::string &expected )
{
CHECK( remove_color_tags( original ) == expected );
}

TEST_CASE( "string_test" )
{
SECTION( "Case 1 - test remove_color_tags" ) {
test_remove_color_tags( "<color_red>TestString</color>",
"TestString" );
test_remove_color_tags( "TestStringWithoutOpeningColorTag</color>",
"TestStringWithoutOpeningColorTag" );
test_remove_color_tags( "<color_yellow>TestStringWithoutClosingColorTag",
"TestStringWithoutClosingColorTag" );
test_remove_color_tags( "<color_green>Test</color>StringWithMultiple<color_light_gray>ColorTags",
"TestStringWithMultipleColorTags" );
}
}

TEST_CASE( "trim_by_length" )
{
CHECK( trim_by_length( "ABC", 2 ) == "A…" );
CHECK( trim_by_length( "ABC", 3 ) == "ABC" );
CHECK( trim_by_length( "ABCDEF", 4 ) == "ABC…" );
CHECK( trim_by_length( "AB文字", 6 ) == "AB文字" );
CHECK( trim_by_length( "AB文字", 5 ) == "AB文…" );
CHECK( trim_by_length( "AB文字", 4 ) == "AB…" );
CHECK( trim_by_length( "MRE 主菜(鸡肉意大利香蒜沙司通心粉)(新鲜)",
5 ) == "MRE …" );
CHECK( trim_by_length( "MRE 主菜(鸡肉意大利香蒜沙司通心粉)(新鲜)",
6 ) == "MRE …" );
CHECK( trim_by_length( "MRE 主菜(鸡肉意大利香蒜沙司通心粉)(新鲜)",
36 ) == "MRE 主菜(鸡肉意大利香蒜沙司通心粉…" );
}