Skip to content

Commit

Permalink
npctalk: add true/false text responses in JSON
Browse files Browse the repository at this point in the history
Add a new response option for response text, "truefalsetext", which
takes a condition and displays a "true" text if the condition is true
and false otherwise.  The response trial, effects, etc. are the same
for both texts.
  • Loading branch information
mlangsdorf committed Jan 19, 2019
1 parent 7ed2053 commit f59ceae
Show file tree
Hide file tree
Showing 3 changed files with 69 additions and 22 deletions.
14 changes: 14 additions & 0 deletions doc/NPCs.md
Original file line number Diff line number Diff line change
Expand Up @@ -378,6 +378,20 @@ The player will always have the option to return to a previous topic or end the
will otherwise have the option to give a $500, $50, or $5 bribe if they have the funds. If they
don't have at least $50, they will also have the option to provide some other bribe.
### truefalsetext
The player will have one response text if a condition is true, and another if it is false, but the same trial for either line. `condition`, `true`, and `false` are all mandatory.
```C++
{
"truefalsetext": {
"condition": { "u_has_cash": 800 },
"true": "I may have the money, I'm not giving you any.",
"false": "I don't have that money."
},
"topic": "TALK_WONT_PAY"
}
```

### text
Will be shown to the user, no further meaning.

Expand Down
10 changes: 10 additions & 0 deletions src/dialogue.h
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,13 @@ struct talk_response {
* displayed.
*/
std::string text;
/*
* Optional responses from a true/false test that defaults to true.
*/
std::string truetext;
std::string falsetext;
std::function<bool( const dialogue & )> truefalse_condition;

talk_trial trial;
/**
* The following values are forwarded to the chatbin of the NPC (see @ref npc_chatbin).
Expand Down Expand Up @@ -297,6 +304,9 @@ struct dynamic_line_t {
}
};

// the truly awful declaration for the conditional_t loading helper_function
void read_dialogue_condition( JsonObject &jo, std::function<bool( const dialogue & )> &condition,
bool default_val );
/**
* A condition for a response spoken by the player.
* This struct only adds the constructors which will load the data from json
Expand Down
67 changes: 45 additions & 22 deletions src/npctalk.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -763,7 +763,10 @@ talk_response &dialogue::add_response( const std::string &text, const std::strin
const bool first )
{
talk_response result = talk_response();
result.text = text;
result.truetext = text;
result.truefalse_condition = []( const dialogue & ) {
return true;
};
result.success.next_topic = talk_topic( r );
if( first ) {
responses.insert( responses.begin(), result );
Expand Down Expand Up @@ -1677,6 +1680,7 @@ void dialogue::add_topic( const talk_topic &topic )
talk_data talk_response::create_option_line( const dialogue &d, const char letter )
{
std::string ftext;
text = truefalse_condition( d ) ? truetext : falsetext;
if( trial != TALK_TRIAL_NONE ) { // dialogue w/ a % chance to work
ftext = string_format( pgettext( "talk option", "%1$c: [%2$s %3$d%%] %4$s" ),
letter, // option letter
Expand Down Expand Up @@ -1821,7 +1825,7 @@ talk_topic dialogue::opt( dialogue_window &d_win, const talk_topic &topic )

talk_response chosen = responses[ch];
std::string response_printed = string_format( pgettext( "you say something", "You: %s" ),
chosen.text );
response_lines[ch].second.substr( 3 ) );
d_win.add_to_history( response_printed );

if( chosen.mission_selected != nullptr ) {
Expand Down Expand Up @@ -2302,7 +2306,17 @@ talk_response::talk_response( JsonObject jo )
if( jo.has_member( "failure" ) ) {
failure = talk_effect_t( jo.get_object( "failure" ) );
}
text = _( jo.get_string( "text" ) );
if( jo.has_member( "truefalsetext" ) ) {
JsonObject truefalse_jo = jo.get_object( "truefalsetext" );
read_dialogue_condition( truefalse_jo, truefalse_condition, true );
truetext = _( truefalse_jo.get_string( "true" ) );
falsetext = _( truefalse_jo.get_string( "false" ) );
} else {
truetext = _( jo.get_string( "text" ) );
truefalse_condition = []( const dialogue & ) {
return true;
};
}
// TODO: mission_selected
// TODO: skill
// TODO: style
Expand All @@ -2314,6 +2328,33 @@ json_talk_response::json_talk_response( JsonObject jo )
load_condition( jo );
}

void read_dialogue_condition( JsonObject &jo, std::function<bool( const dialogue & )> &condition,
bool default_val )
{
const auto null_function = [default_val]( const dialogue & ) {
return default_val;
};

static const std::string member_name( "condition" );
if( !jo.has_member( member_name ) ) {
condition = null_function;
} else if( jo.has_string( member_name ) ) {
const std::string type = jo.get_string( member_name );
conditional_t sub_condition( type );
condition = [sub_condition]( const dialogue & d ) {
return sub_condition( d );
};
} else if( jo.has_object( member_name ) ) {
const JsonObject con_obj = jo.get_object( member_name );
conditional_t sub_condition( con_obj );
condition = [sub_condition]( const dialogue & d ) {
return sub_condition( d );
};
} else {
jo.throw_error( "invalid condition syntax", member_name );
}
}

conditional_t::conditional_t( JsonObject jo )
{
const auto parse_array = []( JsonObject jo, const std::string &type ) {
Expand Down Expand Up @@ -2641,25 +2682,7 @@ void json_talk_response::load_condition( JsonObject &jo )
{
is_switch = jo.get_bool( "switch", false );
is_default = jo.get_bool( "default", false );
static const std::string member_name( "condition" );
if( !jo.has_member( member_name ) ) {
// Leave condition unset, defaults to true.
return;
} else if( jo.has_string( member_name ) ) {
const std::string type = jo.get_string( member_name );
conditional_t sub_condition( type );
condition = [sub_condition]( const dialogue & d ) {
return sub_condition( d );
};
} else if( jo.has_object( member_name ) ) {
const JsonObject con_obj = jo.get_object( member_name );
conditional_t sub_condition( con_obj );
condition = [sub_condition]( const dialogue & d ) {
return sub_condition( d );
};
} else {
jo.throw_error( "invalid condition syntax", member_name );
}
read_dialogue_condition( jo, condition, true );
}

bool json_talk_response::test_condition( const dialogue &d ) const
Expand Down

0 comments on commit f59ceae

Please sign in to comment.