Longer words take longer to animate in

main
parent cfeac39e67
commit bbd1cd5786

109
main.c

@ -980,7 +980,8 @@ void remember_action(Entity *to_modify, Action a, MemoryContext context)
push_memory(to_modify, MD_S8(a.speech, a.speech_length), a.kind, (ActionArgument){0}, context, false); push_memory(to_modify, MD_S8(a.speech, a.speech_length), a.kind, (ActionArgument){0}, context, false);
if(context.i_said_this) if(context.i_said_this)
{ {
to_modify->words_said = 0.0; to_modify->words_said = 0;
to_modify->word_anim_in = 0;
} }
} }
@ -2633,6 +2634,29 @@ typedef struct
bool was_last_said; bool was_last_said;
} DialogElement; } DialogElement;
MD_String8List last_said_without_unsaid_words(MD_Arena *arena, Entity *it)
{
MD_ArenaTemp scratch = MD_GetScratch(&arena, 1);
MD_String8List by_word = split_by_word(scratch.arena, last_said_sentence(it));
MD_String8Node *cur = by_word.first;
MD_String8List without_unsaid_words = {0};
for(int i = 0; i < by_word.node_count; i++)
{
if(i >= it->words_said)
{
break;
}
else
{
assert(cur);
MD_S8ListPush(arena, &without_unsaid_words, cur->string);
cur = cur->next;
}
}
MD_ReleaseScratch(scratch);
return without_unsaid_words;
}
// Some perceptions can have multiple dialog elements. // Some perceptions can have multiple dialog elements.
// Like item give perceptions that have an action with both dialog // Like item give perceptions that have an action with both dialog
// and an argument. So worst case every perception has 2 dialog // and an argument. So worst case every perception has 2 dialog
@ -2655,23 +2679,7 @@ Dialog produce_dialog(Entity *talking_to, bool character_names)
if(last_said_sentence(talking_to).str == it->speech) if(last_said_sentence(talking_to).str == it->speech)
{ {
new_element.was_last_said = true; new_element.was_last_said = true;
MD_String8List by_word = split_by_word(scratch.arena, MD_S8(it->speech, it->speech_length)); my_speech = MD_S8ListJoin(scratch.arena, last_said_without_unsaid_words(scratch.arena, talking_to), &(MD_StringJoin){.mid = MD_S8Lit(" ")});
MD_String8Node *cur = by_word.first;
MD_String8List without_unsaid_words = {0};
for(int i = 0; i < by_word.node_count; i++)
{
if(i >= (int)talking_to->words_said)
{
break;
}
else
{
assert(cur);
MD_S8ListPush(scratch.arena, &without_unsaid_words, cur->string);
cur = cur->next;
}
}
my_speech = MD_S8ListJoin(scratch.arena, without_unsaid_words, &(MD_StringJoin){.mid = MD_S8Lit(" ")});
} }
MD_String8 dialog_speech = MD_S8Fmt(scratch.arena, "%s: %.*s", characters[it->context.author_npc_kind].name, MD_S8VArg(my_speech)); MD_String8 dialog_speech = MD_S8Fmt(scratch.arena, "%s: %.*s", characters[it->context.author_npc_kind].name, MD_S8VArg(my_speech));
@ -3282,29 +3290,43 @@ void frame(void)
// character speech animation text input // character speech animation text input
if (true) if (true)
{ {
int before = (int)it->words_said;
it->word_anim_in = Lerp((float)it->word_anim_in, unwarped_dt * 15.0f, 1.0f);
MD_ArenaTemp scratch = MD_GetScratch(0, 0); MD_ArenaTemp scratch = MD_GetScratch(0, 0);
if(before < split_by_word(scratch.arena, last_said_sentence(it)).node_count)
{
it->words_said += WORDS_PER_SEC * unwarped_dt;
}
MD_ReleaseScratch(scratch);
if( (int)it->words_said > before) MD_String8List split = split_by_word(scratch.arena, last_said_sentence(it));
if(it->words_said <= split.node_count)
{ {
float dist = LenV2(SubV2(it->pos, player->pos)); it->word_anim_in += CHARACTERS_PER_SEC * unwarped_dt;
float volume = Lerp(-0.6f, clamp01(dist / 70.0f), -1.0f); int characters_in_animating_word = 0;
AudioSample * possible_grunts[] = { MD_String8Node *cur = split.first;
&sound_grunt_0, for(int i = 0; i < it->words_said + 1; i++)
&sound_grunt_1, {
&sound_grunt_2, if(cur)
&sound_grunt_3, {
}; if(i >= it->words_said - 1)
play_audio(possible_grunts[rand() % ARRLEN(possible_grunts)], volume); {
it->word_anim_in = 0.0; characters_in_animating_word = (int)cur->string.size;
break;
}
cur = cur->next;
}
}
if((int)it->word_anim_in + 1 > characters_in_animating_word)
{
it->words_said += 1;
if(it->words_said < split.node_count)
{
it->word_anim_in = 0;
}
float dist = LenV2(SubV2(it->pos, player->pos));
float volume = Lerp(-0.6f, clamp01(dist / 70.0f), -1.0f);
AudioSample * possible_grunts[] = {
&sound_grunt_0,
&sound_grunt_1,
&sound_grunt_2,
&sound_grunt_3,
};
play_audio(possible_grunts[rand() % ARRLEN(possible_grunts)], volume);
}
} }
} }
@ -3764,7 +3786,12 @@ void frame(void)
MD_ArenaTemp scratch = MD_GetScratch(0, 0); MD_ArenaTemp scratch = MD_GetScratch(0, 0);
MD_String8 ai_response = {0}; MD_String8 ai_response = {0};
bool mocking_the_ai_response = true; bool mocking_the_ai_response = false;
#ifdef DEVTOOLS
#ifdef MOCK_AI_RESPONSE
mocking_the_ai_response = true;
#endif
#endif
bool succeeded = true; // couldn't get AI response if false bool succeeded = true; // couldn't get AI response if false
if(mocking_the_ai_response) if(mocking_the_ai_response)
{ {
@ -3804,7 +3831,7 @@ void frame(void)
} }
else else
{ {
ai_response = MD_S8Lit(" Within the player's party, while the player is talking to Meld, you hear: ACT_none \"Better have a good reason for bothering me.\""); ai_response = MD_S8Lit(" Within the player's party, while the player is talking to Meld, you hear: ACT_none \"Better have a good reason for bothering me. fjdskfjdsakfjsdakf\"");
} }
} }
else else
@ -4384,7 +4411,7 @@ void frame(void)
float this_text_scale = text_scale; float this_text_scale = text_scale;
if(it->was_last_said && cur->next == 0) if(it->was_last_said && cur->next == 0)
{ {
this_text_scale *= talking_to->word_anim_in; this_text_scale *= clamp01(talking_to->word_anim_in / (float)cur->text.size);
} }
AABB clipping_aabb = dialog_panel; AABB clipping_aabb = dialog_panel;
clipping_aabb.lower_right.y -= 50.0f; clipping_aabb.lower_right.y -= 50.0f;

@ -232,8 +232,8 @@ typedef struct Entity
BUFF(Memory, REMEMBERED_MEMORIES) memories; BUFF(Memory, REMEMBERED_MEMORIES) memories;
bool direction_of_spiral_pattern; bool direction_of_spiral_pattern;
float dialog_panel_opacity; float dialog_panel_opacity;
double words_said; int words_said;
float word_anim_in; float word_anim_in; // in characters, the fraction a word is animated in is this over its length.
NPCPlayerStanding standing; NPCPlayerStanding standing;
NpcKind npc_kind; NpcKind npc_kind;
PathCacheHandle cached_path; PathCacheHandle cached_path;

@ -8,12 +8,13 @@
#define PLAYER_SPEED 3.5f // in meters per second #define PLAYER_SPEED 3.5f // in meters per second
#define PLAYER_ROLL_SPEED 7.0f #define PLAYER_ROLL_SPEED 7.0f
#define PERCEPTION_HEARING_RAGE (TILE_SIZE*4.0f) #define PERCEPTION_HEARING_RAGE (TILE_SIZE*4.0f)
#define WORDS_PER_SEC 7.0f #define CHARACTERS_PER_SEC 45.0f
#define ARENA_SIZE (1024*1024) #define ARENA_SIZE (1024*1024)
#ifdef DEVTOOLS #ifdef DEVTOOLS
// server url cannot have trailing slash // server url cannot have trailing slash
//#define MOCK_AI_RESPONSE
#define SERVER_DOMAIN "localhost" #define SERVER_DOMAIN "localhost"
#define SERVER_PORT 8090 #define SERVER_PORT 8090
#define IS_SERVER_SECURE 0 #define IS_SERVER_SECURE 0

Loading…
Cancel
Save