Skip to content

Commit

Permalink
Custom Filter loot zone (CleverRaven#32754)
Browse files Browse the repository at this point in the history
  • Loading branch information
davidpwbrown authored and misterprimus committed Sep 21, 2019
1 parent a5ecba3 commit dbedf07
Show file tree
Hide file tree
Showing 4 changed files with 149 additions and 8 deletions.
2 changes: 1 addition & 1 deletion src/activity_item_handling.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1266,7 +1266,7 @@ void activity_on_turn_move_loot( player_activity &, player &p )
// if it is, we can skip such item, if not we move the item to correct pile
// think empty bag on food pile, after you ate the content
if( !mgr.has( id, src ) ) {
const auto &dest_set = mgr.get_near( id, abspos );
const auto &dest_set = mgr.get_near( id, abspos, 60, thisitem );

for( auto &dest : dest_set ) {
const auto &dest_loc = g->m.getlocal( dest );
Expand Down
115 changes: 111 additions & 4 deletions src/clzones.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
#include "game.h"
#include "iexamine.h"
#include "item_category.h"
#include "item_search.h"
#include "itype.h"
#include "json.h"
#include "line.h"
Expand All @@ -22,6 +23,7 @@
#include "string_input_popup.h"
#include "translations.h"
#include "ui.h"
#include "uistate.h"
#include "vehicle.h"
#include "item.h"
#include "player.h"
Expand Down Expand Up @@ -126,6 +128,9 @@ zone_manager::zone_manager()
types.emplace( zone_type_id( "LOOT_WOOD" ),
zone_type( translate_marker( "Loot: Wood" ),
translate_marker( "Destination for firewood and items that can be used as such." ) ) );
types.emplace( zone_type_id( "LOOT_CUSTOM" ),
zone_type( translate_marker( "Loot: Custom" ),
translate_marker( "Destination for loot with a custom filter that you can modify." ) ) );
types.emplace( zone_type_id( "LOOT_IGNORE" ),
zone_type( translate_marker( "Loot: Ignore" ),
translate_marker( "Items inside of this zone are ignored by \"sort out loot\" zone-action." ) ) );
Expand Down Expand Up @@ -157,6 +162,8 @@ std::shared_ptr<zone_options> zone_options::create( const zone_type_id &type )
return std::make_shared<plot_options>();
} else if( type == zone_type_id( "CONSTRUCTION_BLUEPRINT" ) ) {
return std::make_shared<blueprint_options>();
} else if( type == zone_type_id( "LOOT_CUSTOM" ) ) {
return std::make_shared<loot_options>();
}

return std::make_shared<zone_options>();
Expand All @@ -168,6 +175,8 @@ bool zone_options::is_valid( const zone_type_id &type, const zone_options &optio
return dynamic_cast<const plot_options *>( &options ) != nullptr ;
} else if( type == zone_type_id( "CONSTRUCTION_BLUEPRINT" ) ) {
return dynamic_cast<const blueprint_options *>( &options ) != nullptr ;
} else if( type == zone_type_id( "LOOT_CUSTOM" ) ) {
return dynamic_cast<const loot_options *>( &options ) != nullptr ;
}

// ensure options is not derived class for the rest of zone types
Expand Down Expand Up @@ -199,6 +208,25 @@ blueprint_options::query_con_result blueprint_options::query_con()
}
}

loot_options::query_loot_result loot_options::query_loot()
{
int w_height = TERMY / 2;

const int w_width = TERMX / 2;
const int w_y0 = ( TERMY > w_height ) ? ( TERMY - w_height ) / 4 : 0;
const int w_x0 = ( TERMX > w_width ) ? ( TERMX - w_width ) / 2 : 0;

catacurses::window w_con = catacurses::newwin( w_height, w_width, w_y0, w_x0 );
draw_item_filter_rules( w_con, 1, w_height - 1, item_filter_type::FILTER );
string_input_popup()
.title( _( "Filter:" ) )
.width( 55 )
.identifier( "item_filter" )
.max_length( 256 )
.edit( mark );
return changed;
}

plot_options::query_seed_result plot_options::query_seed()
{
player &p = g->u;
Expand Down Expand Up @@ -244,6 +272,43 @@ plot_options::query_seed_result plot_options::query_seed()
}
}

bool loot_options::query_at_creation()
{
return query_loot() != canceled;
}

bool loot_options::query()
{
return query_loot() == changed;
}

std::string loot_options::get_zone_name_suggestion() const
{
if( !mark.empty() ) {
return string_format( _( "Loot: Custom : %s" ), mark );
}
return _( "Loot: Custom : No Filter" );
}

std::vector<std::pair<std::string, std::string>> loot_options::get_descriptions() const
{
std::vector<std::pair<std::string, std::string>> options;
options.emplace_back( std::make_pair( _( "Loot: Custom: " ),
!mark.empty() ? mark : _( "No filter" ) ) );

return options;
}

void loot_options::serialize( JsonOut &json ) const
{
json.member( "mark", mark );
}

void loot_options::deserialize( JsonObject &jo_zone )
{
jo_zone.read( "mark", mark );
}

bool blueprint_options::query_at_creation()
{
return query_con() != canceled;
Expand Down Expand Up @@ -582,16 +647,47 @@ bool zone_manager::has_loot_dest_near( const tripoint &where ) const
return false;
}

const zone_data *zone_manager::get_zone_at( const tripoint &where, const zone_type_id &type ) const
{
for( auto it = zones.rbegin(); it != zones.rend(); ++it ) {
const auto &zone = *it;

if( zone.has_inside( where ) && zone.get_type() == type ) {
return &zone;
}
}
return nullptr;
}

bool zone_manager::custom_loot_has( const tripoint &where, const item *it ) const
{
auto zone = get_zone_at( where, zone_type_id( "LOOT_CUSTOM" ) );
if( !zone || !it ) {
return false;
}
const loot_options options = dynamic_cast<const loot_options &>( zone->get_options() );
std::string filter_string = options.get_mark();
auto z = item_filter_from_string( filter_string );

return z( *it );
}

std::unordered_set<tripoint> zone_manager::get_near( const zone_type_id &type,
const tripoint &where, int range, const faction_id &fac ) const
const tripoint &where, int range, const item *it, const faction_id &fac ) const
{
const auto &point_set = get_point_set( type, fac );
auto near_point_set = std::unordered_set<tripoint>();

for( auto &point : point_set ) {
if( point.z == where.z ) {
if( square_dist( point, where ) <= range ) {
near_point_set.insert( point );
if( it && has( zone_type_id( "LOOT_CUSTOM" ), point ) ) {
if( custom_loot_has( point, it ) ) {
near_point_set.insert( point );
}
} else {
near_point_set.insert( point );
}
}
}
}
Expand All @@ -600,7 +696,13 @@ std::unordered_set<tripoint> zone_manager::get_near( const zone_type_id &type,
for( auto &point : vzone_set ) {
if( point.z == where.z ) {
if( square_dist( point, where ) <= range ) {
near_point_set.insert( point );
if( it && has( zone_type_id( "LOOT_CUSTOM" ), point ) ) {
if( custom_loot_has( point, it ) ) {
near_point_set.insert( point );
}
} else {
near_point_set.insert( point );
}
}
}
}
Expand Down Expand Up @@ -650,7 +752,12 @@ zone_type_id zone_manager::get_near_zone_type_for_item( const item &it,
const tripoint &where ) const
{
auto cat = it.get_category();

if( has_near( zone_type_id( "LOOT_CUSTOM" ), where ) ) {
for( const auto elem : get_near( zone_type_id( "LOOT_CUSTOM" ), where, 60, &it ) ) {
( void )elem;
return zone_type_id( "LOOT_CUSTOM" );
}
}
if( it.has_flag( "FIREWOOD" ) ) {
if( has_near( zone_type_id( "LOOT_WOOD" ), where ) ) {
return zone_type_id( "LOOT_WOOD" );
Expand Down
38 changes: 36 additions & 2 deletions src/clzones.h
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,39 @@ class blueprint_options : public zone_options, public mark_option
void deserialize( JsonObject &jo_zone ) override;
};

class loot_options : public zone_options, public mark_option
{
private:
std::string mark; // basic item filter.

enum query_loot_result {
canceled,
successful,
changed,
};

query_loot_result query_loot();

public:
std::string get_mark() const override {
return mark;
}

bool has_options() const override {
return true;
}

bool query_at_creation() override;
bool query() override;

std::string get_zone_name_suggestion() const override;

std::vector<std::pair<std::string, std::string>> get_descriptions() const override;

void serialize( JsonOut &json ) const override;
void deserialize( JsonObject &jo_zone ) override;
};

/**
* These are zones the player can designate.
*/
Expand Down Expand Up @@ -324,7 +357,7 @@ class zone_manager
const bool invert, const bool enabled,
const tripoint &start, const tripoint &end,
std::shared_ptr<zone_options> options = nullptr );

const zone_data *get_zone_at( const tripoint &where, const zone_type_id &type ) const;
void create_vehicle_loot_zone( class vehicle &vehicle, const point &mount_point,
zone_data &new_zone );

Expand All @@ -346,8 +379,9 @@ class zone_manager
bool has_near( const zone_type_id &type, const tripoint &where, int range = MAX_DISTANCE,
const faction_id &fac = your_fac ) const;
bool has_loot_dest_near( const tripoint &where ) const;
bool custom_loot_has( const tripoint &where, const item *it ) const;
std::unordered_set<tripoint> get_near( const zone_type_id &type, const tripoint &where,
int range = MAX_DISTANCE,
int range = MAX_DISTANCE, const item *it = nullptr,
const faction_id &fac = your_fac ) const;
cata::optional<tripoint> get_nearest( const zone_type_id &type, const tripoint &where,
int range = MAX_DISTANCE,
Expand Down
2 changes: 1 addition & 1 deletion src/game.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6344,7 +6344,7 @@ void game::zones_manager()
as_m.entries.emplace_back( 1, true, '1', _( "Edit name" ) );
as_m.entries.emplace_back( 2, true, '2', _( "Edit type" ) );
as_m.entries.emplace_back( 3, zone.get_options().has_options(), '3',
_( "Edit options" ) );
zone.get_type() == zone_type_id( "LOOT_CUSTOM" ) ? _( "Edit filter" ) : _( "Edit options" ) );
as_m.entries.emplace_back( 4, !zone.get_is_vehicle(), '4', _( "Edit position" ) );
as_m.query();

Expand Down

0 comments on commit dbedf07

Please sign in to comment.