Skip to content

Commit

Permalink
Merge pull request #77637 from ShnitzelX2/ter-furn-copy-from
Browse files Browse the repository at this point in the history
Terrain/furniture: code deduplication and improved "copy-from" support
  • Loading branch information
Maleclypse authored Nov 8, 2024
2 parents ca4f4b3 + 8965712 commit a835de3
Show file tree
Hide file tree
Showing 14 changed files with 492 additions and 434 deletions.
8 changes: 2 additions & 6 deletions data/json/connect_groups.json
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
[
{
"type": "connect_group",
"id": "WALL",
"group_flags": [ "WALL", "CONNECT_WITH_WALL" ],
"connects_to_flags": [ "WALL", "CONNECT_WITH_WALL" ]
"id": "WALL"
},
{
"type": "connect_group",
Expand Down Expand Up @@ -135,8 +133,6 @@
},
{
"type": "connect_group",
"id": "INDOORFLOOR",
"group_flags": [ "INDOORS" ],
"rotates_to_flags": [ "WINDOW", "DOOR" ]
"id": "INDOORFLOOR"
}
]
65 changes: 35 additions & 30 deletions src/construction.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1572,10 +1572,10 @@ bool construct::check_deconstruct( const tripoint_bub_ms &p )
if( here.has_flag_furn( ter_furn_flag::TFLAG_EASY_DECONSTRUCT, p ) ) {
return false;
}
return here.furn( p ).obj().deconstruct.can_do;
return !!here.furn( p ).obj().deconstruct;
}
// terrain can only be deconstructed when there is no furniture in the way
return here.ter( p ).obj().deconstruct.can_do;
return !!here.ter( p ).obj().deconstruct;
}

bool construct::check_up_OK( const tripoint_bub_ms & )
Expand Down Expand Up @@ -1788,21 +1788,21 @@ void construct::done_deconstruct( const tripoint_bub_ms &p, Character &player_ch
// TODO: Make this the argument
if( here.has_furn( p ) ) {
const furn_t &f = here.furn( p ).obj();
if( !f.deconstruct.can_do ) {
if( !f.deconstruct ) {
add_msg( m_info, _( "That %s can not be disassembled!" ), f.name() );
return;
}
if( f.deconstruct.furn_set.str().empty() ) {
if( f.deconstruct->furn_set.str().empty() ) {
here.furn_set( p, furn_str_id::NULL_ID() );
} else {
here.furn_set( p, f.deconstruct.furn_set );
here.furn_set( p, f.deconstruct->furn_set );
}
add_msg( _( "The %s is disassembled." ), f.name() );
item &item_here = here.i_at( p ).size() != 1 ? null_item_reference() : here.i_at( p ).only_item();
const std::vector<item *> drop = here.spawn_items( p,
item_group::items_from( f.deconstruct.drop_group, calendar::turn ) );
if( f.deconstruct.skill.has_value() ) {
deconstruction_practice_skill( f.deconstruct.skill.value() );
item_group::items_from( f.deconstruct->drop_group, calendar::turn ) );
if( f.deconstruct->skill.has_value() ) {
deconstruction_practice_skill( f.deconstruct->skill.value() );
}
// if furniture has liquid in it and deconstructs into watertight containers then fill them
if( f.has_flag( "LIQUIDCONT" ) && item_here.made_of( phase_id::LIQUID ) ) {
Expand All @@ -1825,23 +1825,23 @@ void construct::done_deconstruct( const tripoint_bub_ms &p, Character &player_ch
here.delete_signage( p );
} else {
const ter_t &t = here.ter( p ).obj();
if( !t.deconstruct.can_do ) {
if( !t.deconstruct ) {
add_msg( _( "That %s can not be disassembled!" ), t.name() );
return;
}
if( t.deconstruct.deconstruct_above ) {
if( t.deconstruct->deconstruct_above ) {
const tripoint_bub_ms top = p + tripoint_above;
if( here.has_furn( top ) ) {
add_msg( _( "That %s can not be disassembled, since there is furniture above it." ), t.name() );
return;
}
done_deconstruct( top, player_character );
}
here.ter_set( p, t.deconstruct.ter_set );
here.ter_set( p, t.deconstruct->ter_set );
add_msg( _( "The %s is disassembled." ), t.name() );
here.spawn_items( p, item_group::items_from( t.deconstruct.drop_group, calendar::turn ) );
if( t.deconstruct.skill.has_value() ) {
deconstruction_practice_skill( t.deconstruct.skill.value() );
here.spawn_items( p, item_group::items_from( t.deconstruct->drop_group, calendar::turn ) );
if( t.deconstruct->skill.has_value() ) {
deconstruction_practice_skill( t.deconstruct->skill.value() );
}
}
}
Expand Down Expand Up @@ -2090,34 +2090,39 @@ void construct::do_turn_deconstruct( const tripoint_bub_ms &p, Character &who )
}
return ret;
};
auto deconstruction_will_practice_skill = [ &who ]( auto & skill ) {
auto deconstruction_will_practice_skill = [&who]( auto & skill ) {
return who.get_skill_level( skill.id ) >= skill.min &&
who.get_skill_level( skill.id ) < skill.max;
};

if( here.has_furn( p ) ) {
const furn_t &f = here.furn( p ).obj();
if( !!f.deconstruct.skill &&
deconstruction_will_practice_skill( *f.deconstruct.skill ) ) {
auto deconstruct_query = [&who, &cancel_construction, &deconstruction_will_practice_skill,
&deconstruct_items]( map_common_deconstruct_info & deconstruct, std::string & name ) {
if( !!deconstruct.skill &&
deconstruction_will_practice_skill( deconstruct.skill.value() ) ) {
cancel_construction = !who.query_yn(
_( "Deconstructing the %s will yield:\n%s\nYou feel you might also learn something about %s.\nReally deconstruct?" ),
f.name(), deconstruct_items( f.deconstruct.drop_group ), f.deconstruct.skill->id.obj().name() );
name, deconstruct_items( deconstruct.drop_group ), deconstruct.skill->id.obj().name() );
} else {
cancel_construction = !who.query_yn(
_( "Deconstructing the %s will yield:\n%s\nReally deconstruct?" ),
f.name(), deconstruct_items( f.deconstruct.drop_group ) );
name, deconstruct_items( deconstruct.drop_group ) );
}
};

std::string tname;
if( here.has_furn( p ) ) {
const furn_t &f = here.furn( p ).obj();
if( f.deconstruct ) {
map_furn_deconstruct_info deconstruct = f.deconstruct.value();
tname = f.name();
deconstruct_query( deconstruct, tname );
}
} else {
const ter_t &t = here.ter( p ).obj();
if( !!t.deconstruct.skill &&
deconstruction_will_practice_skill( *t.deconstruct.skill ) ) {
cancel_construction = !who.query_yn(
_( "Deconstructing the %s will yield:\n%s\nYou feel you might also learn something about %s.\nReally deconstruct?" ),
t.name(), deconstruct_items( t.deconstruct.drop_group ), t.deconstruct.skill->id.obj().name() );
} else {
cancel_construction = !who.query_yn(
_( "Deconstructing the %s will yield:\n%s\nReally deconstruct?" ),
t.name(), deconstruct_items( t.deconstruct.drop_group ) );
if( t.deconstruct ) {
map_ter_deconstruct_info deconstruct = t.deconstruct.value();
tname = t.name();
deconstruct_query( deconstruct, tname );
}
}
if( cancel_construction ) {
Expand Down
13 changes: 8 additions & 5 deletions src/faction_camp.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4871,12 +4871,15 @@ int om_harvest_ter( npc &comp, const tripoint_abs_omt &omt_tgt, const ter_id &t,
continue;
}
if( bring_back ) {
for( const item &itm : item_group::items_from( ter_tgt.bash.drop_group,
calendar::turn ) ) {
comp.companion_mission_inv.push_back( itm );
const std::optional<map_ter_bash_info> &bash = ter_tgt.bash;
if( bash ) {
for( const item &itm : item_group::items_from( ter_tgt.bash->drop_group,
calendar::turn ) ) {
comp.companion_mission_inv.push_back( itm );
}
harvested++;
target_bay.ter_set( p, ter_tgt.bash->ter_set );
}
harvested++;
target_bay.ter_set( p, ter_tgt.bash.ter_set );
}
}
}
Expand Down
8 changes: 6 additions & 2 deletions src/field_type.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -309,8 +309,12 @@ void field_type::load( const JsonObject &jo, const std::string_view )
optional( jo, was_loaded, "mopsafe", mopsafe, false );

optional( jo, was_loaded, "decrease_intensity_on_contact", decrease_intensity_on_contact, false );

bash_info.load( jo, "bash", map_bash_info::field, "field " + id.str() );
if( jo.has_object( "bash" ) ) {
if( !bash_info ) {
bash_info.emplace();
}
bash_info->load( jo.get_object( "bash" ), was_loaded, "field " + id.str() );
}
if( was_loaded && jo.has_member( "copy-from" ) && looks_like.empty() ) {
looks_like = jo.get_string( "copy-from" );
}
Expand Down
2 changes: 1 addition & 1 deletion src/field_type.h
Original file line number Diff line number Diff line change
Expand Up @@ -207,7 +207,7 @@ struct field_type {
bool has_elec = false;
bool has_fume = false;
description_affix desc_affix = description_affix::DESCRIPTION_AFFIX_NUM;
map_bash_info bash_info;
std::optional<map_fd_bash_info> bash_info;

// chance, issue, duration, speech
std::tuple<int, std::string, time_duration, translation> npc_complain_data;
Expand Down
23 changes: 12 additions & 11 deletions src/handle_action.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -993,30 +993,31 @@ avatar::smash_result avatar::smash( tripoint_bub_ms &smashp )
}
}
for( std::pair<const field_type_id, field_entry> &fd_to_smsh : here.field_at( smashp ) ) {
const map_bash_info &bash_info = fd_to_smsh.first->bash_info;
if( bash_info.str_min == -1 ) {
const std::optional<map_fd_bash_info> &bash_info = fd_to_smsh.first->bash_info;
if( !bash_info ) {
continue;
}
if( smashskill < bash_info.str_min && one_in( 10 ) ) {
if( smashskill < bash_info->str_min && one_in( 10 ) ) {
add_msg( m_neutral, _( "You don't seem to be damaging the %s." ), fd_to_smsh.first->get_name() );
ret.did_smash = true;
return ret;
} else if( smashskill >= rng( bash_info.str_min, bash_info.str_max ) ) {
sounds::sound( smashp, bash_info.sound_vol, sounds::sound_t::combat, bash_info.sound, true, "smash",
} else if( smashskill >= rng( bash_info->str_min, bash_info->str_max ) ) {
sounds::sound( smashp, bash_info->sound_vol, sounds::sound_t::combat, bash_info->sound, true,
"smash",
"field" );
here.remove_field( smashp, fd_to_smsh.first );
here.spawn_items( smashp, item_group::items_from( bash_info.drop_group, calendar::turn ) );
mod_moves( - bash_info.fd_bash_move_cost );
add_msg( m_info, bash_info.field_bash_msg_success.translated() );
here.spawn_items( smashp, item_group::items_from( bash_info->drop_group, calendar::turn ) );
mod_moves( - bash_info->fd_bash_move_cost );
add_msg( m_info, bash_info->field_bash_msg_success.translated() );
ret.did_smash = true;
ret.success = true;
return ret;
} else {
sounds::sound( smashp, bash_info.sound_fail_vol, sounds::sound_t::combat, bash_info.sound_fail,
sounds::sound( smashp, bash_info->sound_fail_vol, sounds::sound_t::combat, bash_info->sound_fail,
true, "smash",
"field" );

ret.resistance = bash_info.str_min;
ret.resistance = bash_info->str_min;
ret.did_smash = true;
return ret;
}
Expand Down Expand Up @@ -1123,7 +1124,7 @@ avatar::smash_result avatar::smash( tripoint_bub_ms &smashp )
// Bash not effective
g->draw_async_anim( smashp, "bash_ineffective" );
if( one_in( 10 ) ) {
if( here.has_furn( smashp ) && here.furn( smashp ).obj().bash.str_min != -1 ) {
if( here.has_furn( smashp ) && here.furn( smashp ).obj().bash ) {
// %s is the smashed furniture
add_msg( m_neutral, _( "You don't seem to be damaging the %s." ), here.furnname( smashp ) );
} else {
Expand Down
3 changes: 2 additions & 1 deletion src/iexamine.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1713,7 +1713,8 @@ void iexamine::portable_structure( Character &you, const tripoint_bub_ms &examp
}
radius = actor.radius;
} else {
radius = std::max( 1, fid->bash.collapse_radius );
const std::optional<map_furn_bash_info> &furn_bash = fid.obj().bash;
radius = std::max( 1, furn_bash ? furn_bash->collapse_radius : 0 );
}

if( !query_yn( _( "Take down the %s?" ), name ) ) {
Expand Down
Loading

0 comments on commit a835de3

Please sign in to comment.