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

Allow plant mutants to sleep in planter furniture #36005

Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,7 @@
"move_cost_mod": 1,
"required_str": 10,
"looks_like": "t_dirtmound",
"flags": [ "TRANSPARENT", "PLANTABLE", "FLAT", "MOUNTABLE" ],
"flags": [ "TRANSPARENT", "PLANTABLE", "FLAT", "MOUNTABLE", "ALLOW_ROOT" ],
"deconstruct": {
"items": [
{ "item": "2x4", "count": [ 11, 12 ] },
Expand Down
10 changes: 5 additions & 5 deletions data/json/furniture_and_terrain/terrain-floors-outdoors.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
"symbol": ".",
"color": "brown",
"move_cost": 2,
"flags": [ "TRANSPARENT", "DIGGABLE", "FLAT", "PLOWABLE" ],
"flags": [ "TRANSPARENT", "DIGGABLE", "FLAT", "PLOWABLE", "ALLOW_ROOT_WEAK" ],
"bash": { "sound": "thump", "ter_set": "t_null", "str_min": 50, "str_max": 100, "str_min_supported": 100, "bash_below": true }
},
{
Expand All @@ -30,7 +30,7 @@
"color": "brown",
"looks_like": "t_dirt",
"move_cost": 3,
"flags": [ "TRANSPARENT", "DIGGABLE", "FLAT" ],
"flags": [ "TRANSPARENT", "DIGGABLE", "FLAT", "ALLOW_ROOT" ],
"bash": { "sound": "thump", "ter_set": "t_null", "str_min": 50, "str_max": 100, "str_min_supported": 100, "bash_below": true }
},
{
Expand Down Expand Up @@ -88,7 +88,7 @@
"symbol": "#",
"color": "brown",
"move_cost": 3,
"flags": [ "TRANSPARENT", "DIGGABLE", "MOUNTABLE", "NOCOLLIDE", "PLANTABLE" ],
"flags": [ "TRANSPARENT", "DIGGABLE", "MOUNTABLE", "NOCOLLIDE", "PLANTABLE", "ALLOW_ROOT" ],
"bash": { "sound": "thump", "ter_set": "t_null", "str_min": 50, "str_max": 100, "str_min_supported": 100 },
"examine_action": "dirtmound"
},
Expand Down Expand Up @@ -133,7 +133,7 @@
"symbol": "#",
"color": "green",
"move_cost": 3,
"flags": [ "TRANSPARENT", "DIGGABLE", "MOUNTABLE", "NOCOLLIDE" ],
"flags": [ "TRANSPARENT", "DIGGABLE", "MOUNTABLE", "NOCOLLIDE", "ALLOW_ROOT" ],
"bash": { "sound": "thump", "ter_set": "t_dirt", "str_min": 50, "str_max": 100, "str_min_supported": 100 }
},
{
Expand All @@ -145,7 +145,7 @@
"symbol": "#",
"color": "brown",
"move_cost": 3,
"flags": [ "TRANSPARENT", "DIGGABLE", "MOUNTABLE", "NOCOLLIDE", "CONTAINER", "SEALED" ],
"flags": [ "TRANSPARENT", "DIGGABLE", "MOUNTABLE", "NOCOLLIDE", "CONTAINER", "SEALED", "ALLOW_ROOT" ],
"bash": { "sound": "thump", "ter_set": "t_dirt", "str_min": 50, "str_max": 100, "str_min_supported": 100 }
},
{
Expand Down
6 changes: 3 additions & 3 deletions data/json/furniture_and_terrain/terrain-floors_indoor.json
Original file line number Diff line number Diff line change
Expand Up @@ -680,7 +680,7 @@
"move_cost": 2,
"looks_like": "t_dirt",
"roof": "t_rock_roof",
"flags": [ "TRANSPARENT", "SUPPORTS_ROOF", "COLLAPSES", "INDOORS", "FLAT", "ROAD", "PLOWABLE", "DIGGABLE" ],
"flags": [ "TRANSPARENT", "SUPPORTS_ROOF", "COLLAPSES", "INDOORS", "FLAT", "ROAD", "PLOWABLE", "DIGGABLE", "ALLOW_ROOT_WEAK" ],
"bash": { "sound": "thump", "ter_set": "t_null", "str_min": 50, "str_max": 100, "str_min_supported": 100, "bash_below": true }
},
{
Expand Down Expand Up @@ -708,7 +708,7 @@
"color": "brown",
"move_cost": 3,
"roof": "t_rock_roof",
"flags": [ "TRANSPARENT", "SUPPORTS_ROOF", "INDOORS", "FLAT", "DIGGABLE" ],
"flags": [ "TRANSPARENT", "SUPPORTS_ROOF", "INDOORS", "FLAT", "DIGGABLE", "ALLOW_ROOT_WEAK" ],
"bash": { "sound": "thump", "ter_set": "t_null", "str_min": 50, "str_max": 100, "str_min_supported": 100, "bash_below": true }
},
{
Expand All @@ -722,7 +722,7 @@
"symbol": ".",
"color": "light_green",
"move_cost": 2,
"flags": [ "TRANSPARENT", "DIGGABLE", "FLAT", "SUPPORTS_ROOF", "INDOORS" ],
"flags": [ "TRANSPARENT", "DIGGABLE", "FLAT", "SUPPORTS_ROOF", "INDOORS", "ALLOW_ROOT_WEAK" ],
"bash": { "sound": "thump", "ter_set": "t_null", "str_min": 40, "str_max": 100, "str_min_supported": 100, "bash_below": true }
},
{
Expand Down
6 changes: 3 additions & 3 deletions data/json/furniture_and_terrain/terrain-flora.json
Original file line number Diff line number Diff line change
Expand Up @@ -1963,7 +1963,7 @@
"symbol": ".",
"color": "light_green",
"move_cost": 2,
"flags": [ "TRANSPARENT", "DIGGABLE", "FLAT" ],
"flags": [ "TRANSPARENT", "DIGGABLE", "FLAT", "ALLOW_ROOT_WEAK" ],
"bash": { "sound": "thump", "ter_set": "t_null", "str_min": 40, "str_max": 100, "str_min_supported": 100, "bash_below": true }
},
{
Expand All @@ -1974,7 +1974,7 @@
"symbol": ".",
"color": "green",
"move_cost": 2,
"flags": [ "TRANSPARENT", "DIGGABLE", "FLAT", "PLOWABLE" ],
"flags": [ "TRANSPARENT", "DIGGABLE", "FLAT", "PLOWABLE", "ALLOW_ROOT_WEAK" ],
"bash": { "sound": "thump", "ter_set": "t_null", "str_min": 40, "str_max": 100, "str_min_supported": 100, "bash_below": true }
},
{
Expand Down Expand Up @@ -2023,7 +2023,7 @@
"symbol": ".",
"color": "brown",
"move_cost": 2,
"flags": [ "TRANSPARENT", "DIGGABLE", "FLAT", "PLOWABLE" ],
"flags": [ "TRANSPARENT", "DIGGABLE", "FLAT", "PLOWABLE", "ALLOW_ROOT_WEAK" ],
"bash": { "ter_set": "t_null", "str_min": 50, "str_max": 400, "str_min_supported": 100, "bash_below": true }
},
{
Expand Down
2 changes: 2 additions & 0 deletions doc/JSON_FLAGS.md
Original file line number Diff line number Diff line change
Expand Up @@ -502,6 +502,8 @@ List of known flags, used in both `terrain.json` and `furniture.json`.

- ```ALARMED``` Sets off an alarm if smashed.
- ```ALLOW_FIELD_EFFECT``` Apply field effects to items inside ```SEALED``` terrain/furniture.
- ```ALLOW_ROOT``` - Allows plant mutants with Chloromorph mutation sleep on the surface very comfortable
- ```ALLOW_ROOT_WEAK``` - Allows plant mutants with Chloromorph mutation sleep on the surface somewhat comfortable
- ```AUTO_WALL_SYMBOL``` (only for terrain) The symbol of this terrain will be one of the line drawings (corner, T-intersection, straight line etc.) depending on the adjacent terrains.

Example: `-` and `|` are both terrain with the `CONNECT_TO_WALL` flag. `O` does not have the flag, while `X` and `Y` have the `AUTO_WALL_SYMBOL` flag.
Expand Down
2 changes: 2 additions & 0 deletions src/mapdata.h
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,8 @@ struct plant_data {
* HIDE_PLACE - Creature on this tile can't be seen by other creature not standing on adjacent tiles
* BLOCK_WIND - This tile will partially block wind
* FLAT_SURF - Furniture or terrain or vehicle part with flat hard surface (ex. table, but not chair; tree stump, etc.).
* ALLOW_ROOT - Allows plant mutants with Chloromorph mutation sleep on the surface very comfortable
* ALLOW_ROOT_WEAK - Allows plant mutants with Chloromorph mutation sleep on the surface somewhat comfortable
*
* Currently only used for Fungal conversions
* WALL - This terrain is an upright obstacle
Expand Down
141 changes: 134 additions & 7 deletions src/player.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4352,16 +4352,18 @@ void player::try_to_sleep( const time_duration &dur )
bool watersleep = false;
if( has_trait( trait_CHLOROMORPH ) ) {
plantsleep = true;
if( ( ter_at_pos == t_dirt || ter_at_pos == t_pit ||
ter_at_pos == t_dirtmound || ter_at_pos == t_pit_shallow ||
ter_at_pos == t_grass ) && !vp &&
furn_at_pos == f_null ) {
add_msg_if_player( m_good, _( "You relax as your roots embrace the soil." ) );
} else if( vp ) {
// Down to bottom: if in vehicle - can't sleep
if( vp ) {
add_msg_if_player( m_bad, _( "It's impossible to sleep in this wheeled pot!" ) );
} else if( furn_at_pos != f_null ) {
// Else if on wrong furniture - can't sleep
} else if( furn_at_pos != f_null && !( g->m.has_flag_furn( "ALLOW_ROOT", pos() ) || g->m.has_flag_furn( "ALLOW_ROOT_WEAK", pos() ) ) ) {
AlexanderBodnya marked this conversation as resolved.
Show resolved Hide resolved
add_msg_if_player( m_bad,
_( "The humans' furniture blocks your roots. You can't get comfortable." ) );
}
// Then, if on allowed furniture or terrain - can sleep
else if( g->m.has_flag_ter_or_furn( "ALLOW_ROOT", pos() ) || g->m.has_flag_ter_or_furn( "ALLOW_ROOT_WEAK", pos() ) ) {
add_msg_if_player( m_good, _( "You relax as your roots embrace the soil." ) );
// All other clauses (wrong terrain without furniture) - can't sleep
} else { // Floor problems
add_msg_if_player( m_bad, _( "Your roots scrabble ineffectively at the unyielding surface." ) );
}
Expand Down Expand Up @@ -4460,6 +4462,131 @@ void player::try_to_sleep( const time_duration &dur )
assign_activity( activity_id( "ACT_TRY_SLEEP" ), to_moves<int>( dur ) );
}

comfort_level player::base_comfort_value( const tripoint &p ) const
{
// Comfort of sleeping spots is "objective", while sleep_spot( p ) is "subjective"
// As in the latter also checks for fatigue and other variables while this function
// only looks at the base comfyness of something. It's still subjective, in a sense,
// as arachnids who sleep in webs will find most places comfortable for instance.
int comfort = 0;

bool plantsleep = has_trait( trait_CHLOROMORPH );
bool fungaloid_cosplay = has_trait( trait_M_SKIN3 );
bool websleep = has_trait( trait_WEB_WALKER );
bool webforce = has_trait( trait_THRESH_SPIDER ) && ( has_trait( trait_WEB_SPINNER ) ||
( has_trait( trait_WEB_WEAVER ) ) );
bool in_shell = has_active_mutation( trait_SHELL2 );
bool watersleep = has_trait( trait_WATERSLEEP );

const optional_vpart_position vp = g->m.veh_at( p );
const maptile tile = g->m.maptile_at( p );
const trap &trap_at_pos = tile.get_trap_t();
const ter_id ter_at_pos = tile.get_ter();
const furn_id furn_at_pos = tile.get_furn();

int web = g->m.get_field_intensity( p, fd_web );

// Some mutants have different comfort needs
if( !plantsleep && !webforce ) {
if( in_shell ) {
comfort += 1 + static_cast<int>( comfort_level::slightly_comfortable );
// Note: shelled individuals can still use sleeping aids!
} else if( vp ) {
vehicle &veh = vp->vehicle();
const cata::optional<vpart_reference> carg = vp.part_with_feature( "CARGO", false );
const cata::optional<vpart_reference> board = vp.part_with_feature( "BOARDABLE", true );
if( carg ) {
vehicle_stack items = veh.get_items( carg->part_index() );
for( auto &items_it : items ) {
if( items_it.has_flag( "SLEEP_AID" ) ) {
// Note: BED + SLEEP_AID = 9 pts, or 1 pt below very_comfortable
comfort += 1 + static_cast<int>( comfort_level::slightly_comfortable );
add_msg_if_player( m_info, _( "You use your %s for comfort." ), items_it.tname() );
break; // prevents using more than 1 sleep aid
}
}
}
if( board ) {
comfort += board->info().comfort;
} else {
comfort -= g->m.move_cost( p );
}
}
// Not in a vehicle, start checking furniture/terrain/traps at this point in decreasing order
else if( furn_at_pos != f_null ) {
comfort += 0 + furn_at_pos.obj().comfort;
}
// Web sleepers can use their webs if better furniture isn't available
else if( websleep && web >= 3 ) {
comfort += 1 + static_cast<int>( comfort_level::slightly_comfortable );
} else if( ter_at_pos == t_improvised_shelter ) {
comfort += 0 + static_cast<int>( comfort_level::slightly_comfortable );
} else if( ter_at_pos == t_floor || ter_at_pos == t_floor_waxed ||
ter_at_pos == t_carpet_red || ter_at_pos == t_carpet_yellow ||
ter_at_pos == t_carpet_green || ter_at_pos == t_carpet_purple ) {
comfort += 1 + static_cast<int>( comfort_level::neutral );
} else if( !trap_at_pos.is_null() ) {
comfort += 0 + trap_at_pos.comfort;
} else {
// Not a comfortable sleeping spot
comfort -= g->m.move_cost( p );
}

auto items = g->m.i_at( p );
for( auto &items_it : items ) {
if( items_it.has_flag( "SLEEP_AID" ) ) {
// Note: BED + SLEEP_AID = 9 pts, or 1 pt below very_comfortable
comfort += 1 + static_cast<int>( comfort_level::slightly_comfortable );
add_msg_if_player( m_info, _( "You use your %s for comfort." ), items_it.tname() );
break; // prevents using more than 1 sleep aid
}
}

if( fungaloid_cosplay && g->m.has_flag_ter_or_furn( "FUNGUS", pos() ) ) {
comfort += static_cast<int>( comfort_level::very_comfortable );
} else if( watersleep && g->m.has_flag_ter( "SWIMMABLE", pos() ) ) {
comfort += static_cast<int>( comfort_level::very_comfortable );
}
} else if( plantsleep ) {
// Sleep ain't happening in a vehicle or on inappropriate furniture
if( vp || !( g->m.has_flag_furn( "ALLOW_ROOT", pos() ) || g->m.has_flag_furn( "ALLOW_ROOT_WEAK", pos() ) ) ){
AlexanderBodnya marked this conversation as resolved.
Show resolved Hide resolved
comfort = static_cast<int>( comfort_level::impossible );
}
// It's very easy for Chloromorphs to get to sleep on soil!
else if( g->m.has_flag_ter_or_furn( "ALLOW_ROOT", pos() ) ) {
comfort += static_cast<int>( comfort_level::very_comfortable );
}
// Not as much if you have to dig through stuff first
else if( g->m.has_flag_ter_or_furn( "ALLOW_ROOT_WEAK", pos() )) {
comfort += static_cast<int>( comfort_level::comfortable );
}
// No sleeping anywhere else
else {
comfort = static_cast<int>( comfort_level::impossible );
}
// Has webforce
} else {
if( web >= 3 ) {
// Thick Web and you're good to go
comfort += static_cast<int>( comfort_level::very_comfortable );
} else {
comfort = static_cast<int>( comfort_level::impossible );
}
}

if( comfort > static_cast<int>( comfort_level::comfortable ) ) {
return comfort_level::very_comfortable;
} else if( comfort > static_cast<int>( comfort_level::slightly_comfortable ) ) {
return comfort_level::comfortable;
} else if( comfort > static_cast<int>( comfort_level::neutral ) ) {
return comfort_level::slightly_comfortable;
} else if( comfort == static_cast<int>( comfort_level::neutral ) ) {
return comfort_level::neutral;
} else {
return comfort_level::uncomfortable;
}
}

int player::sleep_spot( const tripoint &p ) const
{
const int current_stim = get_stim();
Expand Down