From 067f6ad06d6a8b6b86ae80f84a7a25ce45b679bd Mon Sep 17 00:00:00 2001
From: Eric <52087122+Ramza13@users.noreply.github.com>
Date: Fri, 15 Dec 2023 16:38:21 -0500
Subject: [PATCH] Allow excluding items lacking flags (#70171)
* First
* Test fix
---
data/mods/TEST_DATA/EOC.json | 16 ++++++++++++++++
doc/EFFECT_ON_CONDITION.md | 2 +-
src/npctalk.cpp | 9 +++++++++
tests/eoc_test.cpp | 10 ++++++++++
4 files changed, 36 insertions(+), 1 deletion(-)
diff --git a/data/mods/TEST_DATA/EOC.json b/data/mods/TEST_DATA/EOC.json
index 3fa87d2835e3e..5f525e00bc992 100644
--- a/data/mods/TEST_DATA/EOC.json
+++ b/data/mods/TEST_DATA/EOC.json
@@ -81,6 +81,22 @@
"id": "EOC_run_inv_test4_nested",
"effect": [ { "npc_add_var": "key4", "type": "general", "context": "run_inv_test", "value": "yes" } ]
},
+ {
+ "type": "effect_on_condition",
+ "id": "EOC_run_inv_test5_nested",
+ "effect": [ { "npc_add_var": "key5", "type": "general", "context": "run_inv_test", "value": "yes" } ]
+ },
+ {
+ "type": "effect_on_condition",
+ "id": "EOC_run_inv_test5",
+ "effect": [
+ {
+ "u_run_inv_eocs": "all",
+ "true_eocs": [ "EOC_run_inv_test5_nested" ],
+ "search_data": [ { "excluded_flags": [ "BELT_CLIP" ] } ]
+ }
+ ]
+ },
{
"type": "effect_on_condition",
"id": "EOC_item_math_test",
diff --git a/doc/EFFECT_ON_CONDITION.md b/doc/EFFECT_ON_CONDITION.md
index e7e4f2b7f05b3..9622559f0a7f2 100644
--- a/doc/EFFECT_ON_CONDITION.md
+++ b/doc/EFFECT_ON_CONDITION.md
@@ -1901,7 +1901,7 @@ Run EOCs on items in your or NPC's inventory
| Syntax | Optionality | Value | Info |
| --- | --- | --- | --- |
| "u_run_inv_eocs" / "npc_run_inv_eocs" | **mandatory** | string or [variable object](#variable-object) | way the item would be picked;
values can be:
`all` - all items that match the conditions are picked;
`random` - from all items that match the conditions, one picked;
`manual` - menu is open with all items that can be picked, and you can choose one;
`manual_mult` - same as `manual`, but multiple items can be picked |
-| "search_data" | optional | `search_data` | sets the condition for the target item; lack of search_data means any item can be picked; conditions can be:
`id` - id of a specific item;
`category` - category of an item (case sensitive, should always be in lower case);
`flags`- flag or flags the item has
`material` - material of an item;
`worn_only` - if true, return only items, that are worn;
`wielded_only` - if true, return only wielded items |
+| "search_data" | optional | `search_data` | sets the condition for the target item; lack of search_data means any item can be picked; conditions can be:
`id` - id of a specific item;
`category` - category of an item (case sensitive, should always be in lower case);
`flags`- flag or flags the item has
`excluded_flags`- flag or flags the item doesn't have
`material` - material of an item;
`worn_only` - if true, return only items, that are worn;
`wielded_only` - if true, return only wielded items |
| "title" | optional | string or [variable object](#variable-object) | name of the menu, that would be shown, if `manual` or `manual_mult` is used |
| "true_eocs" / "false_eocs" | optional | string, [variable object](##variable-object), inline EoC, or range of all of them | if item was picked successfully, all EoCs from `true_eocs` are run, otherwise all EoCs from `false_eocs` are run; picked item is returned as npc; for example, `n_hp()` return hp of an item |
diff --git a/src/npctalk.cpp b/src/npctalk.cpp
index 18ccb930ab882..81fd4789325b9 100644
--- a/src/npctalk.cpp
+++ b/src/npctalk.cpp
@@ -162,6 +162,7 @@ struct item_search_data {
item_category_id category;
material_id material;
std::vector flags;
+ std::vector excluded_flags;
bool worn_only;
bool wielded_only;
@@ -172,6 +173,9 @@ struct item_search_data {
for( std::string flag : jo.get_string_array( "flags" ) ) {
flags.emplace_back( flag );
}
+ for( std::string flag : jo.get_string_array( "excluded_flags" ) ) {
+ excluded_flags.emplace_back( flag );
+ }
worn_only = jo.get_bool( "worn_only", false );
wielded_only = jo.get_bool( "wielded_only", false );
}
@@ -191,6 +195,11 @@ struct item_search_data {
return false;
}
}
+ for( flag_id flag : excluded_flags ) {
+ if( loc->has_flag( flag ) ) {
+ return false;
+ }
+ }
if( worn_only && !guy->is_worn( *loc ) ) {
return false;
}
diff --git a/tests/eoc_test.cpp b/tests/eoc_test.cpp
index 4d1fbce5bf30a..c1a9fbf8fae44 100644
--- a/tests/eoc_test.cpp
+++ b/tests/eoc_test.cpp
@@ -92,6 +92,7 @@ static const effect_on_condition_id effect_on_condition_EOC_run_inv_test1( "EOC_
static const effect_on_condition_id effect_on_condition_EOC_run_inv_test2( "EOC_run_inv_test2" );
static const effect_on_condition_id effect_on_condition_EOC_run_inv_test3( "EOC_run_inv_test3" );
static const effect_on_condition_id effect_on_condition_EOC_run_inv_test4( "EOC_run_inv_test4" );
+static const effect_on_condition_id effect_on_condition_EOC_run_inv_test5( "EOC_run_inv_test5" );
static const effect_on_condition_id effect_on_condition_EOC_run_until_test( "EOC_run_until_test" );
static const effect_on_condition_id effect_on_condition_EOC_run_with_test( "EOC_run_with_test" );
static const effect_on_condition_id
@@ -972,6 +973,15 @@ TEST_CASE( "EOC_run_inv_test", "[eoc]" )
CHECK( items_after.size() == 1 );
+ // Test search_data: excluded flags
+ CHECK( effect_on_condition_EOC_run_inv_test5->activate( d ) );
+
+ items_after = get_avatar().items_with( []( const item & it ) {
+ return it.get_var( "npctalk_var_general_run_inv_test_key5" ) == "yes";
+ } );
+
+ CHECK( items_after.size() == 3 );
+
// Flag test for item
CHECK( effect_on_condition_EOC_item_flag_test->activate( d ) );