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

Custom Filter loot zone #32754

Merged
merged 8 commits into from Aug 3, 2019
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
120 changes: 116 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,44 @@ 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 =
std::vector<std::pair<std::string, std::string>>();
This conversation was marked as resolved.
Show resolved Hide resolved
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 +648,51 @@ 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 *item_type ) const
{
auto zone = get_zone_at( where, zone_type_id( "LOOT_CUSTOM" ) );
if( !zone || !item_type ) {
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 );


if( z( *item_type ) ) {
This conversation was marked as resolved.
Show resolved Hide resolved
return true;
}
return false;
}

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 *item_type, const faction_id &fac ) const
This conversation was marked as resolved.
Show resolved Hide resolved
{
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( item_type && has( zone_type_id( "LOOT_CUSTOM" ), point ) ) {
if( custom_loot_has( point, item_type ) ) {
near_point_set.insert( point );
}
} else {
near_point_set.insert( point );
}
}
}
}
Expand All @@ -600,7 +701,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( item_type && has( zone_type_id( "LOOT_CUSTOM" ), point ) ) {
if( custom_loot_has( point, item_type ) ) {
near_point_set.insert( point );
}
} else {
near_point_set.insert( point );
}
}
}
}
Expand Down Expand Up @@ -650,7 +757,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
39 changes: 37 additions & 2 deletions src/clzones.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
#include <memory>
#include <string>

#include "item.h"
This conversation was marked as resolved.
Show resolved Hide resolved
#include "optional.h"
#include "point.h"
#include "string_id.h"
Expand Down Expand Up @@ -169,6 +170,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 +358,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 +380,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 *item_type ) 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 *item_type = 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 @@ -6318,7 +6318,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