diff --git a/main.c b/main.c index 39f4437..337c6c7 100644 --- a/main.c +++ b/main.c @@ -2340,6 +2340,40 @@ void frame(void) it->character_say_timer -= character_say_time; } } + if(it->standing == STANDING_FIGHTING || it->standing == STANDING_JOINED) + { + Entity *targeting = player; + Vec2 to_player = NormV2(SubV2(targeting->pos, it->pos)); + Vec2 target_vel = NormV2(AddV2(rotate_counter_clockwise(to_player), MulV2F(to_player, 0.5f))); + target_vel = MulV2F(target_vel, 3.0f); + it->vel = LerpV2(it->vel, 15.0f * dt, target_vel); + it->pos = move_and_slide((MoveSlideParams){it, it->pos, MulV2F(it->vel, pixels_per_meter * dt)}); + + if(it->standing == STANDING_FIGHTING) + { + it->shotgun_timer += dt; + Vec2 to_player = NormV2(SubV2(targeting->pos, it->pos)); + if(it->shotgun_timer >= 1.0f) + { + it->shotgun_timer = 0.0f; + const float spread = (float)PI/4.0f; + // shoot shotgun + int num_bullets = 5; + for(int i = 0; i < num_bullets; i++) + { + Vec2 dir = to_player; + float theta = Lerp(-spread/2.0f, ((float)i / (float)(num_bullets - 1)), spread/2.0f); + dir = RotateV2(dir, theta); + Entity *new_bullet = new_entity(); + new_bullet->is_bullet = true; + new_bullet->pos = AddV2(it->pos, MulV2F(dir, 20.0f)); + new_bullet->vel = MulV2F(dir, 15.0f); + it->vel = AddV2(it->vel, MulV2F(dir, -3.0f)); + } + } + + } + } if(it->npc_kind == NPC_OldMan) { /* diff --git a/makeprompt.h b/makeprompt.h index 31b64d4..3f9ebd8 100644 --- a/makeprompt.h +++ b/makeprompt.h @@ -74,6 +74,13 @@ typedef enum CharacterState CHARACTER_TALKING, } CharacterState; +typedef enum +{ + STANDING_INDIFFERENT, + STANDING_JOINED, + STANDING_FIGHTING, +} NPCPlayerStanding; + typedef struct Entity { bool exists; @@ -107,6 +114,7 @@ typedef struct Entity BUFF(Perception, REMEMBERED_PERCEPTIONS) remembered_perceptions; double character_say_timer; int characters_said; + NPCPlayerStanding standing; NpcKind npc_kind; ItemKind last_seen_holding_kind; #ifdef WEB @@ -151,7 +159,20 @@ void fill_available_actions(Entity *it, AvailableActions *a) } else { - BUFF_APPEND(a, ACT_fights_player); + if(it->standing == STANDING_INDIFFERENT) + { + BUFF_APPEND(a, ACT_fights_player); + BUFF_APPEND(a, ACT_joins_player); + } + else if(it->standing == STANDING_JOINED) + { + BUFF_APPEND(a, ACT_leaves_player); + BUFF_APPEND(a, ACT_fights_player); + } + else if(it->standing == STANDING_FIGHTING) + { + BUFF_APPEND(a, ACT_leaves_player); + } if(npc_is_knight_sprite(it)) { BUFF_APPEND(a, ACT_strikes_air); @@ -182,6 +203,18 @@ void process_perception(Entity *it, Perception p) it->target_goto = AddV2(it->pos, V2(-50.0, 0.0)); it->moved = true; } + else if(p.npc_action_type == ACT_fights_player) + { + it->standing = STANDING_FIGHTING; + } + else if(p.npc_action_type == ACT_leaves_player) + { + it->standing = STANDING_INDIFFERENT; + } + else if(p.npc_action_type == ACT_joins_player) + { + it->standing = STANDING_JOINED; + } } } diff --git a/maketraining.c b/maketraining.c index 343de8e..e785971 100644 --- a/maketraining.c +++ b/maketraining.c @@ -15,6 +15,9 @@ typedef struct #define PlayerItemChange(new_item) { .type = PlayerHeldItemChanged, .holding = new_item, } TrainingSample samples[] = { + // Vim regexes to be ran in order to automatically convert debug print versions of conversations + // s/Player: \(.*\)/PlayerSay(\1),/g + // s/[A-Z_a-z ]*: ACT \([a-zA-Z_]*\) \(.*\)/NPCDoSay(ACT_\1, \2), { .npc_kind = NPC_OldMan, .perceptions = { @@ -96,6 +99,31 @@ TrainingSample samples[] = { NPCDoSay(ACT_heals_player, "No need for me to speak then."), }, }, + { + .npc_kind = NPC_OldMan, + .perceptions = { + PlayerSay("Join me"), + NPCDoSay(ACT_none, "I can"), + PlayerSay("Please"), + NPCDoSay(ACT_none, "Though I shouldn't"), + PlayerSay("Why not?"), + NPCDoSay(ACT_none, "Because then death would win"), + PlayerSay("Why would you joining me cause death to win?"), + NPCDoSay(ACT_none, "I don't know that I can make it, kid. I'm feeling old and weary."), + PlayerSay("So?"), + NPCDoSay(ACT_joins_player, "You know what...You're right. Let's kick Death's ass"), + }, + }, + { + .npc_kind = NPC_Blocky, + .perceptions = { + PlayerItemChange(ITEM_Tripod), + PlayerSay("Move"), + NPCDoSay(ACT_none, "I'm just standing here."), + PlayerSay("Move out of the way"), + NPCDoSay(ACT_allows_player_to_pass, "You have the tripod, so let you pass I shall"), + }, + }, }; diff --git a/server/main.go b/server/main.go index 3227dde..1cf4c01 100644 --- a/server/main.go +++ b/server/main.go @@ -308,7 +308,7 @@ func index(w http.ResponseWriter, req *http.Request) { ctx := context.Background() req := gogpt.CompletionRequest { - Model: "curie:ft-alnar-games-2023-03-31-02-21-14", + Model: "curie:ft-alnar-games-2023-03-31-03-25-44", MaxTokens: 80, Prompt: promptString, Temperature: 0.9, diff --git a/todo.txt b/todo.txt index 060f2bd..c17269b 100644 --- a/todo.txt +++ b/todo.txt @@ -1,7 +1,7 @@ Happening by END OF STREAM: DONE - Payment working DONE - Fixed timesep the gameplay (which means separate player rendering) - - Maybe factor actions! into the game to replace ** stuff. In beginning of each line before quotes, have ACT@fights_player, or other actions, and by default ACT@nothing to force AI to say something about what action is performed +DONE - Maybe factor actions! into the game to replace ** stuff. In beginning of each line before quotes, have ACT@fights_player, or other actions, and by default ACT@nothing to force AI to say something about what action is performed - Help you fight and fight you actions - New characters/items from fate - New art in