Add angel and angel dialog, but can't talk to it yet

main
parent c45c5c4fb2
commit dcf23ca8e4

Binary file not shown.

@ -6,6 +6,10 @@
{ {
filepath: "maninblack.png", filepath: "maninblack.png",
} }
@image angel:
{
filepath: "angel.png",
}
@image unread_triangle: @image unread_triangle:
{ {
filepath: "unread_triangle.png", filepath: "unread_triangle.png",
@ -22,6 +26,10 @@
{ {
filepath: "simple_text_chirp.wav", filepath: "simple_text_chirp.wav",
} }
@sound angel_grunt_0:
{
filepath: "angel_grunt_0.wav",
}
@sound grunt_0: @sound grunt_0:
{ {
filepath: "grunt_0.wav", filepath: "grunt_0.wav",

BIN
assets/angel.png (Stored with Git LFS)

Binary file not shown.

Binary file not shown.

@ -32,6 +32,10 @@
{enum: Daniel, dialog: "Exactly what I'll do to you if you don't keep your mouth shut", to: Raphael, action: ACT_put_shotgun_away} {enum: Daniel, dialog: "Exactly what I'll do to you if you don't keep your mouth shut", to: Raphael, action: ACT_put_shotgun_away}
{enum: Raphael, dialog: "Y-y-y-yes sir.", to: Daniel} {enum: Raphael, dialog: "Y-y-y-yes sir.", to: Daniel}
{can_hear: [Devil, Angel]}
{enum: Devil, dialog: "You will fall!", to: Angel}
{enum: Angel, dialog: "Perhaps. And then I will rise as He has, from the corpse and ashes, the sun rises.", to: Devil}
/* /*
{can_hear: [WellDweller, Farmer, ManInBlack]}, {can_hear: [WellDweller, Farmer, ManInBlack]},
{enum: WellDweller, dialog: "What a fearful farm you live in, come down to the well, the grass is damper down here.", to: Farmer, mood: Scared, thoughts: "Nobody can take me from my well"}, {enum: WellDweller, dialog: "What a fearful farm you live in, come down to the well, the grass is damper down here.", to: Farmer, mood: Scared, thoughts: "Nobody can take me from my well"},

@ -29,6 +29,11 @@ ActionInfo actions[] = {
.description = "Do nothing", .description = "Do nothing",
NO_ARGUMENT, NO_ARGUMENT,
}, },
{
.name = "approach",
.description = "There has been an error, please report to the developer. No NPCs should be able to do this",
ARGUMENT("Expects the argument to be who you're approaching"),
},
{ {
.name = "join", .name = "join",
.description = "Joins somebody else's party, so you follow them everywhere", .description = "Joins somebody else's party, so you follow them everywhere",
@ -101,4 +106,9 @@ CharacterGen characters[] = {
.enum_name = "Passerby", .enum_name = "Passerby",
.prompt = CHARACTER_PROMPT_PREFIX("Random Passerby") "random person, just passing by", .prompt = CHARACTER_PROMPT_PREFIX("Random Passerby") "random person, just passing by",
}, },
{
.name = "Angel",
.enum_name = "Angel",
.prompt = CHARACTER_PROMPT_PREFIX("Angel") "mysterious, radiant, mystical creature the player first talks to. You guide the entire game: deciding on an objective for the player to fulfill until you believe they've learned their lesson, whatever that means to them.",
},
}; };

100
main.c

@ -365,6 +365,7 @@ float float_rand(float min, float max)
float scale = rand() / (float) RAND_MAX; /* [0, 1.0] */ float scale = rand() / (float) RAND_MAX; /* [0, 1.0] */
return min + scale * (max - min); /* [min, max] */ return min + scale * (max - min); /* [min, max] */
} }
// always randomizes pitch
void play_audio(AudioSample *sample, float volume) void play_audio(AudioSample *sample, float volume)
{ {
AudioPlayer *to_use = 0; AudioPlayer *to_use = 0;
@ -3158,6 +3159,7 @@ Armature player_armature = {0};
Armature farmer_armature = {0}; Armature farmer_armature = {0};
Armature shifted_farmer_armature = {0}; Armature shifted_farmer_armature = {0};
Armature man_in_black_armature = {0}; Armature man_in_black_armature = {0};
Armature angel_armature = {0};
// armatureanimations are processed once every visual frame from this list // armatureanimations are processed once every visual frame from this list
Armature *armatures[] = { Armature *armatures[] = {
@ -3165,6 +3167,7 @@ Armature *armatures[] = {
&farmer_armature, &farmer_armature,
&shifted_farmer_armature, &shifted_farmer_armature,
&man_in_black_armature, &man_in_black_armature,
&angel_armature,
}; };
Mesh mesh_player = {0}; Mesh mesh_player = {0};
@ -3232,6 +3235,9 @@ void init(void)
man_in_black_armature = load_armature(persistent_arena, binary_file, MD_S8Lit("Man In Black")); man_in_black_armature = load_armature(persistent_arena, binary_file, MD_S8Lit("Man In Black"));
man_in_black_armature.image = image_man_in_black; man_in_black_armature.image = image_man_in_black;
angel_armature = load_armature(persistent_arena, binary_file, MD_S8Lit("Angel"));
angel_armature.image = image_angel;
binary_file = MD_LoadEntireFile(frame_arena, MD_S8Lit("assets/exported_3d/Farmer.bin")); binary_file = MD_LoadEntireFile(frame_arena, MD_S8Lit("assets/exported_3d/Farmer.bin"));
farmer_armature = load_armature(persistent_arena, binary_file, MD_S8Lit("Farmer.bin")); farmer_armature = load_armature(persistent_arena, binary_file, MD_S8Lit("Farmer.bin"));
@ -3731,10 +3737,11 @@ void flush_quad_batch()
typedef enum typedef enum
{ {
LAYER_TILEMAP, LAYER_INVALID,
LAYER_WORLD, LAYER_WORLD,
LAYER_UI, LAYER_UI,
LAYER_UI_FG, LAYER_UI_FG,
LAYER_UI_TEXTINPUT,
LAYER_SCREENSPACE_EFFECTS, LAYER_SCREENSPACE_EFFECTS,
LAYER_LAST LAYER_LAST
@ -3965,7 +3972,7 @@ void line(Vec2 from, Vec2 to, float line_width, Color color)
} }
#ifdef DEVTOOLS #ifdef DEVTOOLS
bool show_devtools = true; bool show_devtools = false;
#ifdef PROFILING #ifdef PROFILING
extern bool profiling; extern bool profiling;
#else #else
@ -4204,6 +4211,7 @@ typedef struct TextParams
Color *colors; // color per character, if not null must be array of same length as text Color *colors; // color per character, if not null must be array of same length as text
bool do_clipping; bool do_clipping;
LoadedFont *use_font; // if null, uses default font LoadedFont *use_font; // if null, uses default font
Layer layer;
} TextParams; } TextParams;
// returns bounds. To measure text you can set dry run to true and get the bounds // returns bounds. To measure text you can set dry run to true and get the bounds
@ -4297,7 +4305,12 @@ AABB draw_text(TextParams t)
col = t.colors[i]; col = t.colors[i];
} }
draw_quad((DrawParams) { to_draw, font.image, font_atlas_region, col, t.clip_to, .layer = LAYER_UI_FG, .do_clipping = t.do_clipping }); Layer to_use = LAYER_UI_FG;
if(t.layer != LAYER_INVALID)
{
to_use = t.layer;
}
draw_quad((DrawParams) { to_draw, font.image, font_atlas_region, col, t.clip_to, .layer = to_use, .do_clipping = t.do_clipping });
} }
} }
} }
@ -5570,6 +5583,8 @@ void frame(void)
to_use = &farmer_armature; to_use = &farmer_armature;
else if(it->npc_kind == NPC_Raphael) else if(it->npc_kind == NPC_Raphael)
to_use = &man_in_black_armature; to_use = &man_in_black_armature;
else if(it->npc_kind == NPC_Angel)
to_use = &angel_armature;
else else
assert(false); assert(false);
@ -5671,15 +5686,15 @@ void frame(void)
// @Place(text input drawing) // @Place(text input drawing)
#ifdef DESKTOP #ifdef DESKTOP
draw_quad((DrawParams){quad_at(V2(0,screen_size().y), screen_size()), IMG(image_white_square), blendalpha(BLACK, text_input_fade*0.3f), .layer = LAYER_UI_FG}); draw_quad((DrawParams){quad_at(V2(0,screen_size().y), screen_size()), IMG(image_white_square), blendalpha(BLACK, text_input_fade*0.3f), .layer = LAYER_UI_TEXTINPUT});
Vec2 edge_of_text = MulV2F(screen_size(), 0.5f); Vec2 edge_of_text = MulV2F(screen_size(), 0.5f);
if(text_input_buffer_length > 0) if(text_input_buffer_length > 0)
{ {
AABB bounds = draw_centered_text((TextParams){false, MD_S8(text_input_buffer, text_input_buffer_length), MulV2F(screen_size(), 0.5f), blendalpha(WHITE, text_input_fade), 1.0f, .use_font = &font_for_text_input}); AABB bounds = draw_centered_text((TextParams){false, MD_S8(text_input_buffer, text_input_buffer_length), MulV2F(screen_size(), 0.5f), blendalpha(WHITE, text_input_fade), 1.0f, .use_font = &font_for_text_input, .layer = LAYER_UI_TEXTINPUT});
edge_of_text = bounds.lower_right; edge_of_text = bounds.lower_right;
} }
Vec2 cursor_center = V2(edge_of_text.x,screen_size().y/2.0f); Vec2 cursor_center = V2(edge_of_text.x,screen_size().y/2.0f);
draw_quad((DrawParams){quad_centered(cursor_center, V2(3.0f, 80.0f)), IMG(image_white_square), blendalpha(WHITE, text_input_fade * (sinf((float)elapsed_time*8.0f)/2.0f + 0.5f)), .layer = LAYER_UI_FG}); draw_quad((DrawParams){quad_centered(cursor_center, V2(3.0f, 80.0f)), IMG(image_white_square), blendalpha(WHITE, text_input_fade * (sinf((float)elapsed_time*8.0f)/2.0f + 0.5f)), .layer = LAYER_UI_TEXTINPUT});
#endif #endif
// Draw Tilemap draw tilemap tilemap drawing // Draw Tilemap draw tilemap tilemap drawing
@ -5877,10 +5892,8 @@ void frame(void)
static bool player_in_combat = false; static bool player_in_combat = false;
float speed_target = 1.0f; float speed_target = 1.0f;
gs.stopped_time = cur_unread_entity != 0; gs.stopped_time = cur_unread_entity != 0 || (!gs.no_angel_screen);
if(gs.stopped_time) speed_target = 0.0f; if(gs.stopped_time) speed_target = 0.0f;
// pausing the game // pausing the game
speed_factor = Lerp(speed_factor, unwarped_dt*10.0f, speed_target); speed_factor = Lerp(speed_factor, unwarped_dt*10.0f, speed_target);
@ -6851,6 +6864,75 @@ ISANERROR("Don't know how to do this stuff on this platform.")
draw_centered_text((TextParams){false, MD_S8Lit("The AI server is having technical difficulties..."), text_center, WHITE, 1.0f }); draw_centered_text((TextParams){false, MD_S8Lit("The AI server is having technical difficulties..."), text_center, WHITE, 1.0f });
} }
// angel screen
{
static float visible = 1.0f;
bool should_be_visible = !gs.no_angel_screen;
visible = Lerp(visible, unwarped_dt*2.0f, should_be_visible ? 1.0f : 0.0f);
Entity *angel_entity = 0;
ENTITIES_ITER(gs.entities)
{
if(it->is_npc && it->npc_kind == NPC_Angel)
{
assert(!angel_entity);
angel_entity = it;
}
}
assert(angel_entity);
if(should_be_visible) gs.player->talking_to = frome(angel_entity);
draw_quad((DrawParams) {quad_at(V2(0,screen_size().y), screen_size()), IMG(image_white_square), blendalpha(BLACK, visible), .layer = LAYER_UI_FG});
static MD_String8List to_say = {0};
static double cur_characters = 0;
if(to_say.node_count == 0)
{
to_say = split_by_word(persistent_arena, MD_S8Lit("You've been asleep for a long long time..."));
cur_characters = 0;
}
MD_String8 cur_word = {0};
MD_String8Node *cur_word_node = 0;
double chars_said = cur_characters;
for(MD_String8Node *cur = to_say.first; cur; cur = cur->next)
{
if((int)chars_said < cur->string.size)
{
cur_word = cur->string;
cur_word_node = cur;
break;
}
chars_said -= (double)cur->string.size;
}
if(!cur_word.str)
{
cur_word = to_say.last->string;
cur_word_node = to_say.last;
}
cur_characters += unwarped_dt*ANGEL_CHARACTERS_PER_SEC;
chars_said += unwarped_dt*ANGEL_CHARACTERS_PER_SEC;
if(chars_said > cur_word.size && cur_word_node->next)
{
play_audio(&sound_angel_grunt_0, 1.0f);
}
assert(cur_word_node);
MD_String8Node *prev_next = cur_word_node->next;
cur_word_node->next = 0;
MD_String8 without_unsaid = MD_S8ListJoin(frame_arena, to_say, &(MD_StringJoin){.mid = MD_S8Lit(" ")});
cur_word_node->next = prev_next;
draw_centered_text((TextParams){false, without_unsaid, V2(screen_size().x*0.5f, screen_size().y*0.75f), blendalpha(WHITE, visible), 1.0f, .use_font = &font_for_text_input});
draw_centered_text((TextParams){false, MD_S8Lit("(Press E to speak)"), V2(screen_size().x*0.5f, screen_size().y*0.25f), blendalpha(WHITE, visible*0.5f), 0.8f, .use_font = &font_for_text_input});
if(pressed.interact)
{
begin_text_input();
}
}
// win screen // win screen
{ {
static float visible = 0.0f; static float visible = 0.0f;

@ -6,6 +6,7 @@
#define PLAYER_SPEED 0.15f // in meters per second #define PLAYER_SPEED 0.15f // in meters per second
#define PERCEPTION_HEARING_RAGE (TILE_SIZE*4.0f) #define PERCEPTION_HEARING_RAGE (TILE_SIZE*4.0f)
#define CHARACTERS_PER_SEC 45.0f #define CHARACTERS_PER_SEC 45.0f
#define ANGEL_CHARACTERS_PER_SEC 35.0f
#define PROPAGATE_ACTIONS_RADIUS 10.0f #define PROPAGATE_ACTIONS_RADIUS 10.0f
#define SWORD_SWIPE_RADIUS (TILE_SIZE*3.0f) #define SWORD_SWIPE_RADIUS (TILE_SIZE*3.0f)
#define ARROW_SPEED 200.0f #define ARROW_SPEED 200.0f

Loading…
Cancel
Save