From d8de5c205bc9e232268f188e8b79a893fc4f50ce Mon Sep 17 00:00:00 2001 From: Cameron Reikes Date: Sun, 18 Jun 2023 02:40:48 -0700 Subject: [PATCH] Add sword of nazareth, when used inspires adventure among nearby NPCs --- assets.mdesk | 4 ++ assets/new_level.json | 9 ++- assets/swipe.png | Bin 0 -> 5305 bytes character_info.h | 7 +++ main.c | 130 +++++++++++++++++++++++++++++++++++------- tuning.h | 1 + 6 files changed, 129 insertions(+), 22 deletions(-) create mode 100644 assets/swipe.png diff --git a/assets.mdesk b/assets.mdesk index f20601a..0ee5de5 100644 --- a/assets.mdesk +++ b/assets.mdesk @@ -114,6 +114,10 @@ { filepath: "copyrighted/skeleton.png", } +@image swipe: +{ + filepath: "swipe.png", +} /* @image moose: { diff --git a/assets/new_level.json b/assets/new_level.json index 4142fd3..bfe80bc 100644 --- a/assets/new_level.json +++ b/assets/new_level.json @@ -346,6 +346,11 @@ "id":21, "name":"PLAYER", "properties":[ + { + "name":"held_items", + "type":"string", + "value":"{.data = {ITEM_Sword}, .cur_index = 1}" + }, { "name":"standing", "type":"string", @@ -354,8 +359,8 @@ "rotation":0, "visible":true, "width":32, - "x":1537.58503401361, - "y":1842.73469387755 + "x":1502.91836734694, + "y":2585.40136054421 }, { "class":"", diff --git a/assets/swipe.png b/assets/swipe.png new file mode 100644 index 0000000000000000000000000000000000000000..7034218cecd16ac9c341ef4d02728bbd6aa7d04f GIT binary patch literal 5305 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 { BUFF_REMOVE_FRONT(&e->memories); } BUFF_APPEND(&e->memories, new_memory); - if(!context.i_said_this) + if(!new_memory.context.i_said_this) { // self speech doesn't dirty e->perceptions_dirty = true; @@ -1034,7 +1026,17 @@ Entity *get_targeted(Entity *from, NpcKind targeted) void remember_action(Entity *to_modify, Action a, MemoryContext context) { - push_memory(to_modify, MD_S8(a.speech, a.speech_length), MD_S8(a.internal_monologue, a.internal_monologue_length), a.kind, (ActionArgument){0}, context); + Memory new_memory = {0}; + memcpy(new_memory.speech, a.speech, a.speech_length); + new_memory.speech_length = a.speech_length; + memcpy(new_memory.internal_monologue, a.internal_monologue, a.internal_monologue_length); + new_memory.internal_monologue_length = a.internal_monologue_length; + new_memory.action_taken = a.kind; + new_memory.context = context; + new_memory.action_argument = a.argument; + + push_memory(to_modify, new_memory); + if(context.i_said_this) { to_modify->words_said = 0; @@ -1042,6 +1044,7 @@ void remember_action(Entity *to_modify, Action a, MemoryContext context) } } + // returns reason why allocated on arena if invalid // to might be null here, from can't be null MD_String8 is_action_valid(MD_Arena *arena, Entity *from, Action a) @@ -1198,8 +1201,10 @@ void cause_action_side_effects(Entity *from, Action a) typedef struct PropagatingAction { struct PropagatingAction *next; + Action a; MemoryContext context; + Vec2 from; bool already_propagated_to[MAX_ENTITIES]; // tracks by index of entity float progress; // if greater than or equal to 1.0, is freed @@ -1244,6 +1249,43 @@ float propagating_radius(PropagatingAction *p) return Lerp(0.0f, t, PROPAGATE_ACTIONS_RADIUS ); } +typedef struct SwordSwipe +{ + struct SwordSwipe *next; + EntityRef to_ignore; + Vec2 from; + bool already_propagated_to[MAX_ENTITIES]; // tracks by index of entity + float progress; +} SwordSwipe; + +SwordSwipe *swordswipes = 0; + +void push_swipe(SwordSwipe s) +{ + SwordSwipe *to_set = 0; + for(SwordSwipe *cur = swordswipes; cur; cur = cur->next) + { + if(cur->progress >= 1.0f) + { + to_set = cur; + } + } + if(!to_set) + { + to_set = MD_PushArray(persistent_arena, SwordSwipe, 1); + MD_StackPush(swordswipes, to_set); + } + + *to_set = s; +} + +void use_item(Entity *from, ItemKind kind) +{ + if(kind == ITEM_Sword) + { + push_swipe((SwordSwipe){.to_ignore = frome(from), .from = from->pos}); + } +} // only called when the action is instantiated, correctly propagates the information // of the action physically and through the party @@ -3398,6 +3440,10 @@ void draw_item(bool world_space, ItemKind kind, AABB in_aabb, float alpha) { draw_quad((DrawParams) { world_space, drawn, IMG(image_gold_coin), blendalpha(WHITE, alpha), .layer = LAYER_UI_FG }); } + else if (kind == ITEM_Sword) + { + draw_quad((DrawParams) { world_space, drawn, IMG(image_sword), blendalpha(WHITE, alpha), .layer = LAYER_UI_FG }); + } else { assert(false); @@ -3601,6 +3647,32 @@ void frame(void) gs.tick += 1; + PROFILE_SCOPE("handle swipes") // sword swipes + { + for(SwordSwipe *cur = swordswipes; cur; cur = cur->next) + { + if(cur->progress < 1.0f) + { + cur->progress += dt; + ENTITIES_ITER(gs.entities) + { + if(it->is_npc && LenV2(SubV2(it->pos, cur->from)) < SWORD_SWIPE_RADIUS && gete(cur->to_ignore) != it && !cur->already_propagated_to[frome(it).index]) + { + cur->already_propagated_to[frome(it).index] = true; + Memory bravado_memory = {0}; + bravado_memory.internal_monologue_length = (int)strlen(bravado_thought); + memcpy(bravado_memory.internal_monologue, bravado_thought, bravado_memory.internal_monologue_length); + bravado_memory.context.i_said_this = true; + bravado_memory.context.author_npc_kind = it->npc_kind; + + push_memory(it, bravado_memory); + it->perceptions_dirty = true; + } + } + } + } + } + PROFILE_SCOPE("propagate actions") { for(PropagatingAction *cur = propagating; cur; cur = cur->next) @@ -4721,6 +4793,23 @@ void frame(void) } } + PROFILE_SCOPE("draw sword swipes") // draw swipes + { + for(SwordSwipe *cur = swordswipes; cur; cur = cur->next) + { + if(cur->progress < 1.0f) + { + float radius = SWORD_SWIPE_RADIUS; + Quad to_draw = quad_centered(cur->from, V2(radius, radius)); + for(int i = 0; i < 4; i++) + { + to_draw.points[i] = AddV2(RotateV2(SubV2(to_draw.points[i], cur->from), powf(cur->progress * 4.0f, 1.5f)), cur->from); + } + draw_quad((DrawParams){true, to_draw, IMG(image_swipe), blendalpha(WHITE, 1.0f - cur->progress)}); + } + } + } + PROFILE_SCOPE("dialog menu") // big dialog panel draw big dialog panel { static float on_screen = 0.0f; @@ -4925,7 +5014,7 @@ void frame(void) Vec2 item_icon_size = V2(item_icon_width, item_icon_width); Vec2 cursor = AddV2(grid_aabb.upper_left, V2(padding, -padding)); - int to_give = -1; // don't modify the item array while iterating + int pressed_index = -1; BUFF_ITER_I(ItemKind, &player->held_items, i) { Vec2 real_size = LerpV2(item_icon_size, hovered_state[i], MulV2F(item_icon_size, 1.25f)); @@ -4943,10 +5032,7 @@ void frame(void) target = 1.0f; if (pressed.mouse_down) { - if (gete(player->talking_to)) - { - to_give = i; - } + pressed_index = i; } } @@ -4965,21 +5051,25 @@ void frame(void) cursor.x = grid_aabb.upper_left.x + padding; } } - if (to_give > -1) + if (pressed_index > -1) { choosing_item_grid = false; + ItemKind selected_item = player->held_items.data[pressed_index]; if(player->state == CHARACTER_TALKING) { Entity *to = gete(player->talking_to); assert(to); - ItemKind given_item_kind = player->held_items.data[to_give]; - BUFF_REMOVE_AT_INDEX(&player->held_items, to_give); + BUFF_REMOVE_AT_INDEX(&player->held_items, pressed_index); - Action give_action = {.kind = ACT_give_item, .argument = { .item_to_give = given_item_kind }}; + Action give_action = {.kind = ACT_give_item, .argument = { .item_to_give = selected_item }}; perform_action(player, give_action); } + else + { + use_item(player, selected_item); + } } } } diff --git a/tuning.h b/tuning.h index 8f04141..ce2a3be 100644 --- a/tuning.h +++ b/tuning.h @@ -10,6 +10,7 @@ #define PERCEPTION_HEARING_RAGE (TILE_SIZE*4.0f) #define CHARACTERS_PER_SEC 45.0f #define PROPAGATE_ACTIONS_RADIUS (TILE_SIZE*5.0f) +#define SWORD_SWIPE_RADIUS (TILE_SIZE*4.0f) #define ARENA_SIZE (1024*1024)