Skip to content

Commit

Permalink
Better dialog message variable handling (#55775)
Browse files Browse the repository at this point in the history
Co-authored-by: Kevin Granade <[email protected]>
  • Loading branch information
Ramza13 and kevingranade authored Mar 9, 2022
1 parent 75f6658 commit 08f7884
Show file tree
Hide file tree
Showing 4 changed files with 19 additions and 52 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -68,13 +68,13 @@
"context": "artisans",
"op": "==",
"value": 3,
"yes": "Alright so it'll be <u_val:npctalk_var_number_artisans_blacksmith_thickness>mm armor made of the best high carbon steel a woman can scavenge. If you're good with that I'll take the merch up front and start taking some very invasive measurements.",
"no": "Alright so it'll be <u_val:npctalk_var_number_artisans_blacksmith_thickness>mm armor made with some of the best fabrication techniques the world has ever seen. If you're good with that I'll take the merch up front and start taking some very invasive measurements."
"yes": "Alright so it'll be <u_val:number_artisans_blacksmith_thickness>mm armor made of the best high carbon steel a woman can scavenge. If you're good with that I'll take the merch up front and start taking some very invasive measurements.",
"no": "Alright so it'll be <u_val:number_artisans_blacksmith_thickness>mm armor made with some of the best fabrication techniques the world has ever seen. If you're good with that I'll take the merch up front and start taking some very invasive measurements."
},
"responses": [
{ "text": "Forget it.", "topic": "TALK_BLACKSMITH_SERVICES" },
{
"text": "[100 merch] Sounds good. See you in <u_val:npctalk_var_number_artisans_blacksmith_wait> weeks.",
"text": "[100 merch] Sounds good. See you in <u_val:number_artisans_blacksmith_wait> weeks.",
"condition": {
"and": [
{ "u_has_items": { "item": "FMCNote", "count": 100 } },
Expand Down Expand Up @@ -106,7 +106,7 @@
"topic": "TALK_DONE"
},
{
"text": "[300 merch] Sounds good. See you in <u_val:npctalk_var_number_artisans_blacksmith_wait> weeks.",
"text": "[300 merch] Sounds good. See you in <u_val:number_artisans_blacksmith_wait> weeks.",
"condition": {
"and": [
{ "u_has_items": { "item": "FMCNote", "count": 300 } },
Expand Down
2 changes: 1 addition & 1 deletion doc/NPCs.md
Original file line number Diff line number Diff line change
Expand Up @@ -648,7 +648,7 @@ Effect | Description
`u_add_morale: morale_string`, (*optional* `bonus: bonus_int` ), (*optional* `max_bonus: max_bonus_int or max_bonus_variable_object` ), (*optional* `duration: duration_string or duration_variable_object`), (*optional* `decay_start` : `decay_string or decay_variable_object`), (*optional* `capped`: `capped_bool`)<br/> `npc_add_morale: morale_string`, (*optional* `bonus: bonus_int or bonus_variable_object` ), (*optional* `max_bonus: max_bonus_int` ), (*optional* `duration: duration_int`), (*optional*`decay_start` : `decay_int`), (*optional* `capped`: `capped_bool`)| Your character or the NPC will gain a morale bonus of type `morale_string`. Morale is changed by `bonus_int`( or the value of the variable described by `bonus_variable_object` see `variable_object` above) (default 1), with a maximum of up to `max_bonus_int`(or `max_bonus_variable_object`) (default 1). It will last for `duration: duration_string` time (default 1 hour) or `duration_variable_object`. It will begin to decay after `decay_string` time (default 30 minutes) or `decay_variable_object`. `capped_bool` Whether this morale is capped or not, defaults to false.
`u_lose_morale: morale_string`<br/>`npc_lose_morale: morale_string` | Your character or the NPC will lose any morale of type `morale_string`.
`u_add_faction_trust: amount_int`<br/>`u_lose_faction_trust: amount_int` | Your character gains or loses trust with the speaking NPC's faction, which affects which items become available for trading from shopkeepers of that faction.
`u_message, npc_message: message_string`, (*optional* `sound: sound_bool`),(*optional* `outdoor_only: outdoor_only_bool`),(*optional* `snippet: snippet_bool`),(*optional* `same_snippet: snippet_bool`,(*optional* `type: type_string`),(*optional* `popup: popup_bool`) | Displays a message to either the player or the npc of `message_string`. Will not display unless the player or npc is the actual player. If `snippet_bool` is true(defaults to false) it will instead display a random snippet from `message_string` category, if `same_snippet_bool` is true(defaults to false) it will always use the same snippet and will set a variable that can be used for custom item names(this requires the snippets to have id's set). If `sound` is true (defaults to false) it will only display the message if the player is not deaf. `outdoor_only`(defaults to false) only matters when `sound` is true and will make the message less likely to be heard if the player is underground. Message will display as type of `type_string`. Type affects the color of message and can be any of the following values: good, neutral, bad, mixed, warning, info, debug, headshot, critical, grazing. enums.h has more info on each types use. If `popup_bool` is true the message will be in a modal popup the user has to dismiss to continue. You can add variable values into a message by use of the tags `<u_val:var_name>`, `<npc_val:var_name>` or `<global_val:var_name>`.
`u_message, npc_message: message_string`, (*optional* `sound: sound_bool`),(*optional* `outdoor_only: outdoor_only_bool`),(*optional* `snippet: snippet_bool`),(*optional* `same_snippet: snippet_bool`,(*optional* `type: type_string`),(*optional* `popup: popup_bool`) | Displays a message to either the player or the npc of `message_string`. Will not display unless the player or npc is the actual player. If `snippet_bool` is true(defaults to false) it will instead display a random snippet from `message_string` category, if `same_snippet_bool` is true(defaults to false) it will always use the same snippet and will set a variable that can be used for custom item names(this requires the snippets to have id's set). If `sound` is true (defaults to false) it will only display the message if the player is not deaf. `outdoor_only`(defaults to false) only matters when `sound` is true and will make the message less likely to be heard if the player is underground. Message will display as type of `type_string`. Type affects the color of message and can be any of the following values: good, neutral, bad, mixed, warning, info, debug, headshot, critical, grazing. enums.h has more info on each types use. If `popup_bool` is true the message will be in a modal popup the user has to dismiss to continue. You can use any of the Special Custom Entries(defined above).
`u_cast_spell, npc_cast_spell : fake_spell_data` | The spell described by fake_spell_data will be cast with u or the npc as the caster and u or the npc's location as the target. Fake spell data can have the following attributes: `id:string`: the id of the spell to cast, (*optional* `hit_self`: bool ( defaults to false ) if true can hit the caster, `trigger_message`: string to display on trigger, `npc_message`: string for message if npc uses, `max_level` int max level of the spell, `min_level` int min level of the spell )
`u_assign_activity, npc_assign_activity: activity_id_string`, `duration: duration_string or duration_variable_object`) | Your character or the NPC will start activity `activity_id_string`. It will last for `duration: duration_string` time or `duration_variable_object`.
`u_teleport, npc_teleport: target_var_object`, (*optional* `success_message: success_message_string`), (*optional* `fail_message: fail_message_string`) | u or npc are teleported to the destination stored in the variable named by `target_var`. `target_var` is an object with `value`,`type` and `context` as string values and a bool `global` which determines if the variable is global or not. If the teleport succeeds and `success_message` is defined it will be displayed, if it fails and `fail_message` is defined it will be displayed.
Expand Down
55 changes: 11 additions & 44 deletions src/npctalk.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1599,54 +1599,13 @@ void parse_tags( std::string &phrase, const Character &u, const Character &me,
std::string var = tag.substr( tag.find( ':' ) + 1 );
// remove the trailing >
var.pop_back();
phrase.replace( fa, l, u.get_value( var ) );
phrase.replace( fa, l, u.get_value( "npctalk_var_" + var ) );
} else if( tag.find( "<npc_val:" ) != std::string::npos ) {
//adding a npc variable to the string
std::string var = tag.substr( tag.find( ':' ) + 1 );
// remove the trailing >
var.pop_back();
phrase.replace( fa, l, me.get_value( var ) );
} else if( tag.find( "<global_val:" ) != std::string::npos ) {
//adding a global variable to the string
std::string var = tag.substr( tag.find( ':' ) + 1 );
// remove the trailing >
var.pop_back();
global_variables &globvars = get_globals();
phrase.replace( fa, l, globvars.get_global_value( var ) );
} else if( !tag.empty() ) {
debugmsg( "Bad tag. '%s' (%d - %d)", tag.c_str(), fa, fb );
phrase.replace( fa, fb - fa + 1, "????" );
}
} while( fa != std::string::npos && fb != std::string::npos );
}

static void parse_var_tags( std::string &phrase, const dialogue &d )
{
size_t fa;
size_t fb;
std::string tag;
do {
fa = phrase.find( '<' );
fb = phrase.find( '>' );
int l = fb - fa + 1;
if( fa != std::string::npos && fb != std::string::npos ) {
tag = phrase.substr( fa, fb - fa + 1 );
} else {
return;
}

if( tag.find( "<u_val:" ) != std::string::npos ) {
//adding a user variable to the string
std::string var = tag.substr( tag.find( ':' ) + 1 );
// remove the trailing >
var.pop_back();
phrase.replace( fa, l, d.actor( false )->get_value( "npctalk_var_" + var ) );
} else if( tag.find( "<npc_val:" ) != std::string::npos ) {
//adding a npc variable to the string
std::string var = tag.substr( tag.find( ':' ) + 1 );
// remove the trailing >
var.pop_back();
phrase.replace( fa, l, d.actor( true )->get_value( "npctalk_var_" + var ) );
phrase.replace( fa, l, me.get_value( "npctalk_var_" + var ) );
} else if( tag.find( "<global_val:" ) != std::string::npos ) {
//adding a global variable to the string
std::string var = tag.substr( tag.find( ':' ) + 1 );
Expand Down Expand Up @@ -2776,7 +2735,15 @@ void talk_effect_fun_t::set_message( const JsonObject &jo, const std::string &me
} else {
translated_message = _( message );
}
parse_var_tags( translated_message, d );
Character *alpha = d.has_alpha ? d.actor( false )->get_character() : nullptr;
if( !alpha ) {
alpha = &get_player_character();
}
Character *beta = d.has_beta ? d.actor( true )->get_character() : nullptr;
if( !beta ) {
beta = &get_player_character();
}
parse_tags( translated_message, *alpha, *beta );
if( sound ) {
bool display = false;
map &here = get_map();
Expand Down
6 changes: 3 additions & 3 deletions tests/npc_talk_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,7 @@ static npc &prep_test( dialogue &d, bool shopkeep = false )
clear_vehicles();
clear_map();
avatar &player_character = get_avatar();
player_character.set_value( "test_var", "It's avatar" );
player_character.set_value( "npctalk_var_test_var", "It's avatar" );
player_character.name = "Alpha Avatar";
REQUIRE_FALSE( player_character.in_vehicle );

Expand All @@ -139,7 +139,7 @@ static npc &prep_test( dialogue &d, bool shopkeep = false )
g->faction_manager_ptr->create_if_needed();

npc &beta = create_test_talker( shopkeep );
beta.set_value( "test_var", "It's npc" );
beta.set_value( "npctalk_var_test_var", "It's npc" );
d = dialogue( get_talker_for( player_character ), get_talker_for( beta ) );
return beta;
}
Expand Down Expand Up @@ -1067,7 +1067,7 @@ TEST_CASE( "npc_test_tags", "[npc_talk]" )
prep_test( d );

global_variables &globvars = get_globals();
globvars.set_global_value( "test_var", "It's global" );
globvars.set_global_value( "npctalk_var_test_var", "It's global" );

d.add_topic( "TALK_TEST_TAGS" );
gen_response_lines( d, 3 );
Expand Down

0 comments on commit 08f7884

Please sign in to comment.