diff --git a/doc/NPCs.md b/doc/NPCs.md index a936c24809f2e..7be6c6bb3e445 100644 --- a/doc/NPCs.md +++ b/doc/NPCs.md @@ -1289,6 +1289,7 @@ Example | Description `"u_val": "spell_level"` | Level of a given spell. -1 means the spell is not known when read and that the spell should be forgotten if written. Optional params: `school` gives the highest level of spells known of that school (read only), `spell` reads or writes the level of the spell with matching spell id. If no parameter is provided, you will get the highest spell level of the spells you know (read only). `"u_val": "spell_exp"` | Experience for a given spell. -1 means the spell is not known when read and that the spell should be forgotten if written. Required param: `spell` is the id of the spell in question. `"u_val": "spell_level_adjustment"` | Temporary caster level adjustment. Only useable by EoCs that trigger on the event `opens_spellbook`. Old values will be reset to 0 before the event triggers. To avoid overwriting values from other EoCs, it is reccomended to adjust the values here with `+=` or `-=` instead of setting it to an absolute value. When an NPC consider what spell to cast they will be considered the primary talker, so their values are manipulated with `u_val` the same way the player's values are. Optional params: `school` makes it only apply to a given school. `spell` makes it only apply to a given spell. +`"u_val": "spell_count"` | Number of spells that this character knows. Optional params: `school` returns only the number of spells of the specified spell class that the character knows. Read-only. `"u_val": "proficiency"` | Deals with a proficiency. Required params: `proficiency_id` is the id of the proficiency dealt with. `format` determines how the proficiency will be interacted with. `"format": ` will read or write how much you have trained a proficiency out of . So for exaple, if you write a 5 to a proficiency using `"format": 10`, you will set the proficiency to be trained to 50%. `"format": "percent"` reads or writes how many percen done the learning is. `"format": "permille"` does likewise for permille. `"format": "total_time_required"` gives you total time required to train a given proficiency (read only). `"format": "time_spent"` deals with total time spent. `"format": "time_left"` sets the remaining time instead. For most formats possible, If the resulting time is set to equal or more than the time required to learn the proficiency, you learn it. If you read it and it gives back the total time required, it means it is learnt. Setting the total time practiced to a negative value completely removes the proficiency from your known and practiced proficiencies. If you try to read time spent on a proficiency that is not in your proficiency list, you will get back 0 seconds. `"distance": []` | Distance between two targets. Valid targets are: "u","npc" and an object with a variable name.

Example:
"condition": { "compare_num": [
{ "distance": [ "u",{ "u_val": "stuck", "type": "ps", "context": "teleport" } ] },
">", { "const": 5 }
] }
`"hour"` | Hours since midnight. diff --git a/src/condition.cpp b/src/condition.cpp index 44aa1df16a97a..5c6c715f990b4 100644 --- a/src/condition.cpp +++ b/src/condition.cpp @@ -2188,6 +2188,14 @@ std::function conditional_t::get_get_dbl( J const &jo ) return [is_npc, this_spell_id]( dialogue & d ) { return d.actor( is_npc )->get_spell_exp( this_spell_id ); }; + } else if( checked_value == "spell_count" ) { + trait_id school = trait_id::NULL_ID(); + if( jo.has_member( "school" ) ) { + school = trait_id( jo.get_string( "school" ) ); + } + return [is_npc, school]( dialogue & d ) { + return d.actor( is_npc )->get_spell_count( school ); + }; } else if( checked_value == "proficiency" ) { const std::string proficiency_name = jo.get_string( "proficiency_id" ); const proficiency_id the_proficiency_id( proficiency_name ); diff --git a/src/talker.h b/src/talker.h index 0a961fe7d8ede..60bc8306a1efc 100644 --- a/src/talker.h +++ b/src/talker.h @@ -201,6 +201,9 @@ class talker virtual int get_highest_spell_level() const { return 0; } + virtual int get_spell_count( const trait_id & ) const { + return 0; + } virtual void set_spell_level( const spell_id &, int ) {} virtual void set_spell_exp( const spell_id &, int ) {} virtual void set_skill_level( const skill_id &, int ) {} diff --git a/src/talker_character.cpp b/src/talker_character.cpp index a7f1aa1144fa8..28e0b45133d3c 100644 --- a/src/talker_character.cpp +++ b/src/talker_character.cpp @@ -357,6 +357,17 @@ int talker_character_const::get_spell_exp( const spell_id &spell_name ) const return me_chr_const->magic->get_spell( spell_name ).xp(); } +int talker_character_const::get_spell_count( const trait_id &school ) const +{ + int count = 0; + for( const spell *sp : me_chr_const->magic->get_spells() ) { + if( school.is_null() || sp->spell_class() == school ) { + count++; + } + } + return count; +} + void talker_character::set_spell_level( const spell_id &sp, int new_level ) { me_chr->magic->set_spell_level( sp, new_level, me_chr ); diff --git a/src/talker_character.h b/src/talker_character.h index a8513332f1c04..b88183dd188a1 100644 --- a/src/talker_character.h +++ b/src/talker_character.h @@ -82,6 +82,7 @@ class talker_character_const: public talker_cloner int get_spell_level( const spell_id & ) const override; int get_spell_exp( const spell_id & ) const override; int get_highest_spell_level() const override; + int get_spell_count( const trait_id & ) const override; bool knows_proficiency( const proficiency_id &proficiency ) const override; time_duration proficiency_practiced_time( const proficiency_id & ) const override;