Skip to content

Commit

Permalink
Auto eat and drink from auto-zones during long activities/waiting (#3…
Browse files Browse the repository at this point in the history
…6543)

* auto eat and drink from specific zones during activities

* add to docs

* no drunk

* from review: use encapsulated functions and stash cooldown for checking

* add edible frozen flag handling

* check for item_loc valid after eat()

* add timeout to not checking

* Update src/activity_item_handling.cpp

Co-Authored-By: BevapDin <tho_ki@gmx.de>

* Update src/activity_item_handling.cpp

Co-Authored-By: BevapDin <tho_ki@gmx.de>

* redundant check removal

* astyle

Co-authored-by: BevapDin <tho_ki@gmx.de>
  • Loading branch information
ZhilkinSerg and BevapDin authored Apr 4, 2020
2 parents 9f3d7e7 + 4d7c45a commit 2051779
Show file tree
Hide file tree
Showing 9 changed files with 143 additions and 17 deletions.
47 changes: 32 additions & 15 deletions data/json/player_activities.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,8 @@
"verb": "reading",
"rooted": true,
"based_on": "speed",
"refuel_fires": true
"refuel_fires": true,
"auto_needs": true
},
{
"id": "ACT_MULTIPLE_CONSTRUCTION",
Expand All @@ -33,7 +34,8 @@
"based_on": "neither",
"suspendable": false,
"no_resume": true,
"multi_activity": true
"multi_activity": true,
"auto_needs": true
},
{
"id": "ACT_MULTIPLE_MINE",
Expand Down Expand Up @@ -80,7 +82,8 @@
"based_on": "neither",
"suspendable": false,
"no_resume": true,
"multi_activity": true
"multi_activity": true,
"auto_needs": true
},
{
"id": "ACT_MULTIPLE_BUTCHER",
Expand All @@ -90,7 +93,8 @@
"based_on": "neither",
"suspendable": false,
"no_resume": true,
"multi_activity": true
"multi_activity": true,
"auto_needs": true
},
{
"id": "ACT_MULTIPLE_CHOP_TREES",
Expand All @@ -100,14 +104,16 @@
"based_on": "neither",
"suspendable": false,
"no_resume": true,
"multi_activity": true
"multi_activity": true,
"auto_needs": true
},
{
"id": "ACT_MULTIPLE_FISH",
"type": "activity_type",
"activity_level": "LIGHT_EXERCISE",
"verb": "fishing",
"based_on": "neither"
"based_on": "neither",
"auto_needs": true
},
{
"id": "ACT_GENERIC_GAME",
Expand All @@ -133,15 +139,17 @@
"rooted": true,
"based_on": "time",
"no_resume": true,
"refuel_fires": true
"refuel_fires": true,
"auto_needs": true
},
{
"id": "ACT_CRAFT",
"type": "activity_type",
"activity_level": "MODERATE_EXERCISE",
"verb": "crafting",
"based_on": "neither",
"refuel_fires": true
"refuel_fires": true,
"auto_needs": true
},
{
"id": "ACT_DISASSEMBLE",
Expand All @@ -151,7 +159,8 @@
"suspendable": false,
"rooted": true,
"based_on": "speed",
"refuel_fires": true
"refuel_fires": true,
"auto_needs": true
},
{
"id": "ACT_BUTCHER",
Expand Down Expand Up @@ -209,7 +218,8 @@
"verb": "salvaging",
"based_on": "speed",
"no_resume": true,
"refuel_fires": true
"refuel_fires": true,
"auto_needs": true
},
{
"id": "ACT_FORAGE",
Expand All @@ -224,6 +234,7 @@
"activity_level": "ACTIVE_EXERCISE",
"based_on": "neither",
"refuel_fires": true,
"auto_needs": true,
"verb": "constructing"
},
{
Expand Down Expand Up @@ -255,7 +266,8 @@
"verb": "waiting",
"rooted": true,
"based_on": "time",
"no_resume": true
"no_resume": true,
"auto_needs": true
},
{
"id": "ACT_FIRSTAID",
Expand Down Expand Up @@ -403,7 +415,8 @@
"suspendable": false,
"based_on": "neither",
"no_resume": true,
"multi_activity": true
"multi_activity": true,
"auto_needs": true
},
{
"id": "ACT_FERTILIZE_PLOT",
Expand All @@ -412,7 +425,8 @@
"verb": "fertilizing plots",
"suspendable": false,
"based_on": "neither",
"no_resume": true
"no_resume": true,
"auto_needs": true
},
{
"id": "ACT_ADV_INVENTORY",
Expand Down Expand Up @@ -533,7 +547,8 @@
"verb": "repairing",
"rooted": true,
"based_on": "neither",
"refuel_fires": true
"refuel_fires": true,
"auto_needs": true
},
{
"id": "ACT_MEND_ITEM",
Expand All @@ -542,7 +557,8 @@
"verb": "mending",
"rooted": true,
"based_on": "speed",
"refuel_fires": true
"refuel_fires": true,
"auto_needs": true
},
{
"id": "ACT_GUNMOD_ADD",
Expand Down Expand Up @@ -791,6 +807,7 @@
"verb": "studying",
"suspendable": false,
"refuel_fires": true,
"auto_needs": true,
"rooted": true,
"based_on": "time",
"no_resume": true
Expand Down
4 changes: 3 additions & 1 deletion doc/PLAYER_ACTIVITY.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,9 @@ Activities are long term actions, that can be interrupted and (optionally) conti
* speed: `player_activity::moves_left` may be decremented faster or slower, depending on the character's speed.
* neither: `moves_left` will not be decremented. Thus you must define a do_turn function; otherwise the activity will never end!
* no_resume (false): Rather than resuming, you must always restart the activity from scratch.
* multi_activity(false): This activity will repeat until it cannot do any more work, used for NPC and player zone activities.
* multi_activity(false): This activity will repeat until it cannot do any more work, used for NPC and player zone activities.
* refuel_fires( false ): If true, the player will automatically refuel fires during the long activity.
* auto_needs( false ) : If true, the player will automatically eat and drink from specific auto_consume zones during long activities.

## Termination

Expand Down
1 change: 1 addition & 0 deletions src/activity_handlers.h
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,7 @@ bool generic_multi_activity_handler( player_activity &act, player &p, bool check
void activity_on_turn_fetch( player_activity &, player *p );
void activity_on_turn_pickup();
void activity_on_turn_wear( player_activity &act, player &p );
bool find_auto_consume( player &p, bool food );
void try_fuel_fire( player_activity &act, player &p, bool starting_fire = false );

enum class item_drop_reason {
Expand Down
75 changes: 75 additions & 0 deletions src/activity_item_handling.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
#include <utility>

#include "avatar.h"
#include "avatar_action.h"
#include "construction.h"
#include "clzones.h"
#include "debug.h"
Expand Down Expand Up @@ -73,6 +74,7 @@ static const activity_id ACT_VEHICLE( "ACT_VEHICLE" );
static const activity_id ACT_VEHICLE_DECONSTRUCTION( "ACT_VEHICLE_DECONSTRUCTION" );
static const activity_id ACT_VEHICLE_REPAIR( "ACT_VEHICLE_REPAIR" );
static const efftype_id effect_pet( "pet" );
static const efftype_id effect_nausea( "nausea" );

static const trap_str_id tr_firewood_source( "tr_firewood_source" );
static const trap_str_id tr_unfinished_construction( "tr_unfinished_construction" );
Expand Down Expand Up @@ -3032,6 +3034,79 @@ static cata::optional<tripoint> find_refuel_spot_trap( const std::vector<tripoin
return {};
}

bool find_auto_consume( player &p, const bool food )
{
// return false if there is no point searching again while the activity is still happening.
if( p.is_npc() ) {
return false;
}
if( p.has_effect( effect_nausea ) ) {
return true;
}
static const std::string flag_MELTS( "MELTS" );
static const std::string flag_EDIBLE_FROZEN( "EDIBLE_FROZEN" );
const tripoint pos = p.pos();
zone_manager &mgr = zone_manager::get_manager();
zone_type_id consume_type_zone( "" );
if( food ) {
consume_type_zone = zone_type_id( "AUTO_EAT" );
} else {
consume_type_zone = zone_type_id( "AUTO_DRINK" );
}
const std::unordered_set<tripoint> &dest_set = mgr.get_near( consume_type_zone, g->m.getabs( pos ),
ACTIVITY_SEARCH_DISTANCE );
if( dest_set.empty() ) {
return false;
}
for( const tripoint loc : dest_set ) {
if( loc.z != p.pos().z ) {
continue;
}
map_stack food_there = g->m.i_at( g->m.getlocal( loc ) );
for( item &it : food_there ) {
item &comest = p.get_consumable_from( it );
if( comest.is_null() || comest.is_craft() || !comest.is_food() ||
p.fun_for( comest ).first < -5 ) {
// not good eatings.
continue;
}
if( !p.can_consume( it ) ) {
continue;
}
if( food && p.compute_effective_nutrients( comest ).kcal < 50 ) {
// not filling enough
continue;
}
if( !p.will_eat( comest, false ).success() ) {
// wont like it, cannibal meat etc
continue;
}
if( !it.is_owned_by( p, true ) ) {
// it aint ours.
continue;
}
if( !food && comest.get_comestible()->quench < 15 ) {
// not quenching enough
continue;
}
if( !food && it.is_watertight_container() && it.contents_made_of( SOLID ) ) {
// its frozen
continue;
}
p.mod_moves( -Pickup::cost_to_move_item( p, it ) * std::max( rl_dist( p.pos(),
g->m.getlocal( loc ) ), 1 ) );
item_location item_loc( map_cursor( g->m.getlocal( loc ) ), &it );
avatar_action::eat( g->u, item_loc );
// eat() may have removed the item, so check its still there.
if( item_loc.get_item() && item_loc->is_container() ) {
item_loc->on_contents_changed();
}
return true;
}
}
return false;
}

void try_fuel_fire( player_activity &act, player &p, const bool starting_fire )
{
const tripoint pos = p.pos();
Expand Down
1 change: 1 addition & 0 deletions src/activity_type.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ void activity_type::load( const JsonObject &jo )
assign( jo, "no_resume", result.no_resume_, true );
assign( jo, "multi_activity", result.multi_activity_, false );
assign( jo, "refuel_fires", result.refuel_fires, false );
assign( jo, "auto_needs", result.auto_needs, false );

std::string activity_level = jo.get_string( "activity_level", "" );
if( activity_level.empty() ) {
Expand Down
8 changes: 7 additions & 1 deletion src/activity_type.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ class activity_type
bool no_resume_ = false;
bool multi_activity_ = false;
bool refuel_fires = false;
bool auto_needs = false;
float activity_level = NO_EXERCISE;

public:
Expand Down Expand Up @@ -68,7 +69,12 @@ class activity_type
bool will_refuel_fires() const {
return refuel_fires;
}

/**
* If true, player will automatically consume from relevant auto-eat/drink zones during activity
*/
bool valid_auto_needs() const {
return auto_needs;
}
void call_do_turn( player_activity *, player * ) const;
/** Returns whether it had a finish function or not */
bool call_finish( player_activity *, player * ) const;
Expand Down
6 changes: 6 additions & 0 deletions src/clzones.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,12 @@ zone_manager::zone_manager()
types.emplace( zone_type_id( "CAMP_FOOD" ),
zone_type( translate_marker( "Basecamp: Food" ),
translate_marker( "Items in this zone will be added to a basecamp's food supply in the Distribute Food mission." ) ) );
types.emplace( zone_type_id( "AUTO_EAT" ),
zone_type( translate_marker( "Auto Eat" ),
translate_marker( "Items in this zone will be automatically eaten during a long activity if you get hungry." ) ) );
types.emplace( zone_type_id( "AUTO_DRINK" ),
zone_type( translate_marker( "Auto Drink" ),
translate_marker( "Items in this zone will be automatically consumed during a long activity if you get thirsty." ) ) );

}

Expand Down
16 changes: 16 additions & 0 deletions src/player_activity.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,22 @@ void player_activity::do_turn( player &p )
if( *this && type->will_refuel_fires() ) {
try_fuel_fire( *this, p );
}
if( calendar::once_every( 30_minutes ) ) {
no_food_nearby_for_auto_consume = false;
no_drink_nearby_for_auto_consume = false;
}
if( *this && !p.is_npc() && type->valid_auto_needs() && !no_food_nearby_for_auto_consume ) {
if( p.stomach.contains() <= p.stomach.capacity( p ) / 4 && p.get_kcal_percent() < 0.95f ) {
if( !find_auto_consume( p, true ) ) {
no_food_nearby_for_auto_consume = true;
}
}
if( p.get_thirst() > 130 && !no_drink_nearby_for_auto_consume ) {
if( !find_auto_consume( p, false ) ) {
no_drink_nearby_for_auto_consume = true;
}
}
}
if( type->based_on() == based_on_type::TIME ) {
if( moves_left >= 100 ) {
moves_left -= 100;
Expand Down
2 changes: 2 additions & 0 deletions src/player_activity.h
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,8 @@ class player_activity
std::unordered_set<tripoint> coord_set;
std::vector<weak_ptr_fast<monster>> monsters;
tripoint placement;
bool no_drink_nearby_for_auto_consume = false;
bool no_food_nearby_for_auto_consume = false;
/** If true, the activity will be auto-resumed next time the player attempts
* an identical activity. This value is set dynamically.
*/
Expand Down

0 comments on commit 2051779

Please sign in to comment.