Skip to content

Commit

Permalink
[EOC] Port some functions to item talker (CleverRaven#68289)
Browse files Browse the repository at this point in the history
* port teleport to item

* item hp

* document and minor fix

* add test

* add wielded_only

* doc

* enhance run_inv_eocs

* fix errors

* test and documentate

* clang error

* clang warning fix

* add u_has_flag

* add u_set.unset_flag

* add u_activate

* add test

* document

* fix test segfault

* fix clang error
  • Loading branch information
lispcoc authored Sep 29, 2023
1 parent dc54e7e commit 9a4b2e0
Show file tree
Hide file tree
Showing 11 changed files with 543 additions and 73 deletions.
105 changes: 103 additions & 2 deletions data/mods/TEST_DATA/EOC.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
{
"type": "effect_on_condition",
"id": "EOC_run_inv_test1",
"effect": [ { "u_run_inv_eocs": [ "EOC_run_inv_test1_nested" ] } ]
"effect": [ { "u_run_inv_eocs": "all", "true_eocs": [ "EOC_run_inv_test1_nested" ] } ]
},
{
"type": "effect_on_condition",
Expand All @@ -26,13 +26,114 @@
{
"type": "effect_on_condition",
"id": "EOC_run_inv_test2",
"effect": [ { "u_run_inv_eocs": [ "EOC_run_inv_test2_nested" ], "item_ids": [ "backpack" ], "worn_only": true } ]
"effect": [
{
"u_run_inv_eocs": "all",
"true_eocs": [ "EOC_run_inv_test2_nested" ],
"search_data": [ { "id": "backpack", "worn_only": true } ]
}
]
},
{
"type": "effect_on_condition",
"id": "EOC_run_inv_test2_nested",
"effect": [ { "npc_add_var": "key2", "type": "general", "context": "run_inv_test", "value": "yes" } ]
},
{
"type": "effect_on_condition",
"id": "EOC_run_inv_test3",
"effect": [
{
"u_run_inv_eocs": "all",
"true_eocs": [ "EOC_run_inv_test3_nested" ],
"search_data": [ { "material": "wood", "wielded_only": true } ]
}
]
},
{
"type": "effect_on_condition",
"id": "EOC_run_inv_test3_nested",
"effect": [ { "npc_add_var": "key3", "type": "general", "context": "run_inv_test", "value": "yes" } ]
},
{
"type": "effect_on_condition",
"id": "EOC_run_inv_test4",
"effect": [
{
"u_run_inv_eocs": "all",
"true_eocs": [ "EOC_run_inv_test4_nested" ],
"search_data": [ { "category": "weapons", "flags": [ "BELT_CLIP" ] } ]
}
]
},
{
"type": "effect_on_condition",
"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_item_math_test",
"effect": [ { "u_run_inv_eocs": "all", "true_eocs": [ "EOC_item_math_test_nested" ] } ]
},
{
"type": "effect_on_condition",
"id": "EOC_item_math_test_nested",
"effect": [ { "math": [ "n_hp()", "=", "100" ] } ]
},
{
"type": "effect_on_condition",
"id": "EOC_item_teleport_test",
"effect": [
{ "u_location_variable": { "u_val": "tele_test" }, "x_adjust": 1, "y_adjust": 1 },
{ "u_run_inv_eocs": "all", "true_eocs": [ "EOC_item_teleport_test_nested" ] }
]
},
{
"type": "effect_on_condition",
"id": "EOC_item_teleport_test_nested",
"effect": [ { "npc_teleport": { "u_val": "tele_test" } } ]
},
{
"type": "effect_on_condition",
"id": "EOC_item_flag_test",
"effect": [
{
"u_run_inv_eocs": "all",
"true_eocs": [ "EOC_item_flag_test_nested1", "EOC_item_flag_test_nested2", "EOC_item_flag_test_nested3" ],
"search_data": [ { "worn_only": true } ]
}
]
},
{
"type": "effect_on_condition",
"id": "EOC_item_flag_test_nested1",
"effect": [ { "npc_set_flag": "FILTHY" } ]
},
{
"type": "effect_on_condition",
"id": "EOC_item_flag_test_nested2",
"condition": { "npc_has_flag": "FILTHY" },
"effect": [ { "npc_add_var": "is_filthy", "type": "general", "context": "run_inv_test", "value": "yes" } ]
},
{
"type": "effect_on_condition",
"id": "EOC_item_flag_test_nested3",
"effect": [ { "npc_unset_flag": "FILTHY" } ]
},
{
"type": "effect_on_condition",
"id": "EOC_item_activate_test",
"effect": [
{ "u_location_variable": { "u_val": "activate_pos" }, "x_adjust": 1, "y_adjust": 1 },
{ "u_run_inv_eocs": "all", "true_eocs": [ "EOC_item_activate_test_nested" ] }
]
},
{
"type": "effect_on_condition",
"id": "EOC_item_activate_test_nested",
"effect": [ { "u_activate": "deploy_furn", "target_var": { "u_val": "activate_pos" } } ]
},
{
"type": "effect_on_condition",
"id": "EOC_run_until_test",
Expand Down
1 change: 1 addition & 0 deletions data/mods/TEST_DATA/items.json
Original file line number Diff line number Diff line change
Expand Up @@ -3770,6 +3770,7 @@
"mode_modifier": [ [ "REACH", "bayonet", 2, [ "MELEE", "REACH_ATTACK" ] ] ],
"install_time": "5 s"
},
"use_action": { "type": "deploy_furn", "furn_type": "f_cardboard_box" },
"min_skills": [ [ "weapon", 2 ], [ "melee", 1 ] ],
"techniques": [ "RAPID_TEST" ],
"qualities": [ [ "CUT", 2 ], [ "CUT_FINE", 1 ], [ "BUTCHER", 19 ] ],
Expand Down
64 changes: 62 additions & 2 deletions doc/EFFECT_ON_CONDITION.md
Original file line number Diff line number Diff line change
Expand Up @@ -331,7 +331,7 @@ Checks do alpha talker has `FEATHERS` mutation

| Avatar | Character | NPC | Monster | Furniture | Item |
| ------ | --------- | --------- | ---- | ------- | --- |
| ✔️ | ✔️ | ✔️ | ✔️ | ❌ | |
| ✔️ | ✔️ | ✔️ | ✔️ | ❌ | ✔️ |

#### Examples
Alpha talker has `GRAB` flag, and beta talker has `GRAB_FILTER` flag; monster uses it to perform grabs - the game checks do monster (alpha talker, `u_`) has GRAB flag (i.e. able to grab at all), and check is target able to be grabbed using `GRAB_FILTER` flag
Expand Down Expand Up @@ -2008,7 +2008,7 @@ You or NPC is teleported to `target_var` coordinates

| Avatar | Character | NPC | Monster | Furniture | Item |
| ------ | --------- | --------- | ---- | ------- | --- |
| ✔️ | ✔️ | ✔️ ||| |
| ✔️ | ✔️ | ✔️ ||| ✔️ |

##### Examples

Expand Down Expand Up @@ -2093,6 +2093,66 @@ You and NPC both die
}
```

## Item effects

#### `u_set_flag``npc_set_flag`
Give item a flag

| Syntax | Optionality | Value | Info |
| ------ | ----------- | ------ | ---- |
| "u_set_flag" / "npc_set_flag" | **mandatory** | string or [variable object](##variable-object) | id of flag that should be given |

##### Valid talkers:

| Avatar | Character | NPC | Monster | Furniture | Item |
| ------ | --------- | --------- | ---- | ------- | --- |
|||||| ✔️ |

##### Examples
Make item filthy
```json
{ "npc_set_flag": "FILTHY" }
```

#### `u_unset_flag``npc_unset_flag`
Remove a flag from item

| Syntax | Optionality | Value | Info |
| ------ | ----------- | ------ | ---- |
| "u_unset_flag" / "npc_unset_flag" | **mandatory** | string or [variable object](##variable-object) | id of flag that should be remove |

##### Valid talkers:

| Avatar | Character | NPC | Monster | Furniture | Item |
| ------ | --------- | --------- | ---- | ------- | --- |
|||||| ✔️ |

##### Examples
Make item clean
```json
{ "npc_unset_flag": "FILTHY" }
```

#### `u_activate``npc_activate`
You activate beta talker / NPC activates alpha talker. One must be a Character and the other an item.

| Syntax | Optionality | Value | Info |
| ------ | ----------- | ------ | ---- |
| "u_activate" / "npc_activate" | **mandatory** | string or [variable object](##variable-object) | use action id of item that activate |
| "target_var" | optional | [variable object](##variable-object) | if set, target location is forced this variable's coordinates |

##### Valid talkers:

| Avatar | Character | NPC | Monster | Furniture | Item |
| ------ | --------- | --------- | ---- | ------- | --- |
| ✔️ | ✔️ | ✔️ ||||

##### Examples
Force you consume drug item
```json
{ "u_activate": "consume_drug" }
```

## Map Updates

Map updates are related to any change in the map, weather, or coordinates, and any talker can use them
Expand Down
6 changes: 3 additions & 3 deletions doc/NPCs.md
Original file line number Diff line number Diff line change
Expand Up @@ -925,7 +925,7 @@ Effect | Description
`u_roll_remainder, npc_roll_remainder : `array of strings and/or [variable objects](#variable-object), `type: `string or [variable object](#variable-object), (*optional* `true_eocs: eocs_array`), (*optional* `false_eocs: eocs_array`), (*optional* `message: ` string or [variable object](#variable-object) ) | Type must be either `bionic`, `mutation`, `spell` or `recipe`. If the u or npc does not have all of the listed bionics, mutations, spells, or recipes they will be given one randomly and and then all of the effect_on_conditions in `true_eocs` are run, otherwise all the effect_on_conditions in `false_eocs` are run. If `message` is provided and a result is given then the `message` will be displayed as a message with the first instance of `%s` in it replaced with the name of the result selected.
`switch : arithmetic/math_expression`, `cases: effect_array` | Will calculate value of `switch` and then run member of `cases` with the highest `case` that the `switch` is higher or equal to. `cases` is an array of objects with an int_or_var `case` and an `effect` field which is a dialog effect.
`u_run_npc_eocs or npc_run_npc_eocs : effect_on_condition_array`, (*optional* `unique_ids: `array of strings and/or [variable objects](#variable-object)), (*optional* `npcs_must_see: npcs_must_see_bool`), (*optional* `npc_range: `int or [variable object](#variable-object)), (*optional* `local: local_bool`) | Will run all members of the `effect_on_condition_array` on npcs. Members should either be the id of an effect_on_condition or an inline effect_on_condition. If `local`(default: false) is false, then regardless of location all npcs with unique ids in the array `unique_ids` will be affected. If `local` is true, only unique_ids listed in `unique_ids` will be affected, if it is empty all npcs in range will be effected. If a value is given for `npc_range` the npc must be that close to the source and if `npcs_must_see`(defaults to false) is true the npc must be able to see the source. For `u_run_npc_eocs` u is the source for `npc_run_npc_eocs` it is the npc.
`u_run_inv_eocs or npc_run_inv_eocs : effect_on_condition_array`, (*optional* `item_ids: `array of strings and/or [variable objects](#variable-object)), (*optional* `worn_only: worn_only_bool`) | Will run all members of the `effect_on_condition_array` on items in inventory. Members should either be the id of an effect_on_condition or an inline effect_on_condition. If `item_ids` is given, only items with id listed in `item_ids` will be affected. If `worn_only`(default: false) is true, items u or npc wears are only affected. For `u_run_inv_eocs` u is the source for `npc_run_inv_eocs` it is the npc. Items will become the beta talker for the EOC to run.
`u_run_inv_eocs or npc_run_inv_eocs : ` string or [variable object](#variable-object), (*optional* `true_eocs: effect_on_condition_array`), (*optional* `false_eocs: effect_on_condition_array`), (*optional* `search_data: search_data_array`) | Run EOCs on items in u/npc's inventory. For `u_run_inv_eocs` u is the source for `npc_run_inv_eocs` it is the npc. Items will become the beta talker for the EOC to run.<br/> If value is `"all"`, this targets all items that match the condition. If value is `"random"`, this targets one item at random from that match the condition. `true_eocs` runs with items selected as target, `false_eocs` runs with the others. `search_data` sets the condition for the target item, if not given all items will be targeted.<br/><br/> `search_data` accepts one or more conditions such as:<pre> "search_data": [ {<br/> "id": "item_id",<br/> "category": "item_category",<br/> "flags": [ "FLAG_1", "FLAG_2" ],<br/> "worn_only": false,<br/> "wielded_only": true<br/> } ]</pre> All fields are optional. `id`, `category`, `material`, and `flags` set the id, category, material, flags of the target item respectively. `worn_only`, `wielded_only` limit taget to what you wear/wield.
`weighted_list_eocs: array_array` | Will choose one of a list of eocs to activate based on weight. Members should be an array of first the id of an effect_on_condition or an inline effect_on_condition and second an object that resolves to an integer weight.<br/><br/>Example: This will cause "EOC_SLEEP" 1/10 as often as it makes a test message appear.<pre> "effect": [<br/> {<br/> "weighted_list_eocs": [<br/> [ "EOC_SLEEP", { "const": 1 } ],<br/> [ {<br/> "id": "eoc_test2",<br/> "effect": [ { "u_message": "A test message appears!", "type": "bad" } ]<br/> },<br/> { "const": 10 }<br/> ]<br/> ]<br/> }<br/> ]</pre>

#### Detailed Info
Expand Down Expand Up @@ -1433,8 +1433,8 @@ _function arguments are `d`oubles (or sub-expressions), `s`trings, or `v`[ariabl
| armor(`s`/`v`,`s`/`v`) ||| u, n | Return the numerical value for a characters armor on a body part, for a damage type.<br/> Variables are damagetype ID, bodypart ID.<br/> Example:<br/>`"condition": { "math": [ "u_armor('bash', 'torso')", ">=", "5"] }`|
| attack_speed() ||| u, n | Return the characters current adjusted attack speed with their current weapon.<br/> Example:<br/>`"condition": { "math": [ "u_attack_speed()", ">=", "10"] }`|
| effect_intensity(`s`/`v`,...) ||| u, n | Return the characters intensity of effect.<br/> Variable is effect ID.<br/><br/> Optional kwargs:<br/>`bodypart`: `s`/`v` - Specify the bodypart to get/set intensity of effect.<br/><br/> Example:<br/>`"condition": { "math": [ "u_effect_intensity('bite', 'bodypart': 'torso')", ">", "1"] }`|
| hp(`s`/`v`) ||| u, n | Return or set the characters hp.<br/> Variable is bodypart ID. If omitted, get sum of all bodypart or set all bodypart.<br/><br/> Example:<br/>`"condition": { "math": [ "hp('torso')", ">", "100"] }`|
| hp_max(`s`/`v`) ||| u, n | Return the characters max amount of hp on a body part.<br/> Variable is bodypart ID.<br/> Example:<br/>`"condition": { "math": [ "u_hp_max('torso')", ">=", "100"] }`|
| hp(`s`/`v`) ||| u, n | Return or set the characters hp.<br/> Variable is bodypart ID. If omitted, get sum of all bodypart or set all bodypart.<br/> For items, returns current amount of damage required to destroy item. Variable is not required.<br/><br/> Example:<br/>`"condition": { "math": [ "hp('torso')", ">", "100"] }`|
| hp_max(`s`/`v`) ||| u, n | Return the characters max amount of hp on a body part.<br/> Variable is bodypart ID.<br/> For items, returns max amount of damage required to destroy item. Variable is not required. <br/> Example:<br/>`"condition": { "math": [ "u_hp_max('torso')", ">=", "100"] }`|
| game_option(`s`/`v`) ||| N/A<br/>(global) | Return the numerical value of a game option<br/> Example:<br/>`"condition": { "math": [ "game_option('NPC_SPAWNTIME')", ">=", "5"] }`|
| monsters_nearby(`s`/`v`...) ||| u, n, global | Return the number of nearby monsters. Takes any number of `s`tring or `v`ariable positional parameters as monster IDs. <br/><br/>Optional kwargs:<br/>`radius`: `d`/`v` - limit to radius (rl_dist)<br/>`location`: `v` - center search on this location<br/><br/>The `location` kwarg is mandatory in the global scope.<br/><br/>Examples:<br/>`"condition": { "math": [ "u_monsters_nearby('radius': u_search_radius * 3)", ">", "5" ] }`<br/><br/>`"condition": { "math": [ "monsters_nearby('mon_void_maw', 'mon_void_limb', mon_fotm_var, 'radius': u_search_radius * 3, 'location': u_search_loc)", ">", "5" ] }`|
| num_input(`s`/`v`,`d`/`v`) ||| N/A<br/>(global) | Prompt the player for a number.<br/> Variables are Prompt text, Default Value:<br/>`"math": [ "u_value_to_set", "=", "num_input('Playstyle Perks Cost?', 4)" ]`|
Expand Down
5 changes: 4 additions & 1 deletion src/dialogue_helpers.h
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ struct talk_effect_fun_t {
void set_run_eoc_until( const JsonObject &jo, std::string_view member );
void set_run_eoc_selector( const JsonObject &jo, const std::string &member );
void set_run_npc_eocs( const JsonObject &jo, std::string_view member, bool is_npc );
void set_run_inv_eocs( const JsonObject &jo, std::string_view member, bool is_npc );
void set_run_inv_eocs( const JsonObject &jo, const std::string &member, bool is_npc );
void set_queue_eocs( const JsonObject &jo, std::string_view member );
void set_queue_eoc_with( const JsonObject &jo, std::string_view member );
void set_switch( const JsonObject &jo, std::string_view member );
Expand Down Expand Up @@ -127,6 +127,9 @@ struct talk_effect_fun_t {
void set_open_dialogue( const JsonObject &jo, std::string_view member );
void set_take_control( const JsonObject &jo );
void set_take_control_menu();
void set_set_flag( const JsonObject &jo, const std::string &member, bool is_npc );
void set_unset_flag( const JsonObject &jo, const std::string &member, bool is_npc );
void set_activate( const JsonObject &jo, const std::string &member, bool is_npc );
void operator()( dialogue &d ) const {
if( !function ) {
return;
Expand Down
4 changes: 4 additions & 0 deletions src/item_location.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1124,6 +1124,10 @@ std::unique_ptr<talker> get_talker_for( item_location &it )
{
return std::make_unique<talker_item>( &it );
}
std::unique_ptr<talker> get_talker_for( const item_location &it )
{
return std::make_unique<talker_item_const>( &it );
}
std::unique_ptr<talker> get_talker_for( item_location *it )
{
return std::make_unique<talker_item>( it );
Expand Down
1 change: 1 addition & 0 deletions src/item_location.h
Original file line number Diff line number Diff line change
Expand Up @@ -159,5 +159,6 @@ class item_location
std::shared_ptr<impl> ptr;
};
std::unique_ptr<talker> get_talker_for( item_location &it );
std::unique_ptr<talker> get_talker_for( const item_location &it );
std::unique_ptr<talker> get_talker_for( item_location *it );
#endif // CATA_SRC_ITEM_LOCATION_H
Loading

0 comments on commit 9a4b2e0

Please sign in to comment.