NPCs aware of health, bad guy hit diff from good guy

main
Cameron Murphy Reikes 2 years ago
parent e0c794b873
commit 616cceb49c

@ -1657,8 +1657,9 @@ void dbgrect(AABB rect)
} }
// from_point is for knockback // from_point is for knockback
void request_do_damage(Entity *to, Vec2 from_point, float damage) void request_do_damage(Entity *to, Entity *from, float damage)
{ {
Vec2 from_point = from->pos;
if(to == NULL) return; if(to == NULL) return;
if(to->is_bullet) if(to->is_bullet)
{ {
@ -1670,7 +1671,14 @@ void request_do_damage(Entity *to, Vec2 from_point, float damage)
else if(true) else if(true)
{ {
to->damage += damage; to->damage += damage;
process_perception(to, (Perception){.type = PlayerAction, .player_action_type = ACT_hits_npc}); if(from->is_character)
{
process_perception(to, (Perception){.type = PlayerAction, .player_action_type = ACT_hits_npc});
}
else
{
process_perception(to, (Perception){.type = EnemyAction, .enemy_action_type = ACT_hits_npc});
}
to->vel = MulV2F(NormV2(SubV2(to->pos, from_point)), 15.0f); to->vel = MulV2F(NormV2(SubV2(to->pos, from_point)), 15.0f);
} }
else else
@ -2581,7 +2589,7 @@ void frame(void)
Entity *from = it; Entity *from = it;
BUFF_ITER(Entity *, &to_damage) BUFF_ITER(Entity *, &to_damage)
{ {
request_do_damage(*it, from->pos, 0.2f); request_do_damage(*it, from, 0.2f);
} }
} }
} }
@ -2701,7 +2709,7 @@ void frame(void)
if(!it->is_tile && !(it->e->is_bullet)) if(!it->is_tile && !(it->e->is_bullet))
{ {
// knockback and damage // knockback and damage
request_do_damage(it->e, from_bullet->pos, 0.2f); request_do_damage(it->e, from_bullet, 0.2f);
destroy_bullet = true; destroy_bullet = true;
} }
} }
@ -2930,7 +2938,7 @@ void frame(void)
SwordToDamage to_damage = entity_sword_to_do_damage(player, get_overlapping(cur_level, weapon_aabb)); SwordToDamage to_damage = entity_sword_to_do_damage(player, get_overlapping(cur_level, weapon_aabb));
BUFF_ITER(Entity*, &to_damage) BUFF_ITER(Entity*, &to_damage)
{ {
request_do_damage(*it, player->pos, 0.2f); request_do_damage(*it, player, 0.2f);
} }
player->swing_progress += dt; player->swing_progress += dt;
if(player->swing_progress > anim_sprite_duration(&knight_attack)) if(player->swing_progress > anim_sprite_duration(&knight_attack))

@ -281,6 +281,27 @@ void generate_prompt(Entity *it, PromptBuff *into)
printf_buff(into, "%s", prompt_table[it->npc_kind]); printf_buff(into, "%s", prompt_table[it->npc_kind]);
printf_buff(into, "%s", "\n"); printf_buff(into, "%s", "\n");
// npc stats prompt
const char *health_string = 0;
if(it->damage <= 0.2f)
{
health_string = "The NPC hasn't taken much damage, they're healthy.";
}
else if(it->damage <= 0.5f)
{
health_string = "The NPC has taken quite a chunk of damage, they're soon gonna be ready to call it quits.";
}
else if(it->damage <= 0.8f)
{
health_string = "The NPC is close to dying! They want to leave the player's party ASAP";
}
else
{
health_string = "It's over for the NPC, they're basically dead they've taken so much damage. They should get their affairs in order.";
}
assert(health_string);
printf_buff(into, "NPC Health Status: %s\n", health_string);
// item prompt // item prompt
if(it->last_seen_holding_kind != ITEM_none) if(it->last_seen_holding_kind != ITEM_none)
{ {

@ -2,17 +2,27 @@
#include <stdio.h> #include <stdio.h>
#include "makeprompt.h" #include "makeprompt.h"
typedef struct
{
bool is_take_damage;
Perception p;
float damage; // only valid when is take damage
} TrainingElement;
typedef struct typedef struct
{ {
NpcKind npc_kind; NpcKind npc_kind;
Perception perceptions[32]; TrainingElement elems[32];
} TrainingSample; } TrainingSample;
#define PlayerAct(act) { .type = PlayerAction, .player_action_type = act, } #define PlayerAct(act) { .p = { .type = PlayerAction, .player_action_type = act, } }
#define PlayerSay(txt) { .type = PlayerDialog, .player_dialog = SENTENCE_CONST(txt), } #define PlayerSay(txt) { .p = { .type = PlayerDialog, .player_dialog = SENTENCE_CONST(txt), } }
#define NPCDoSay(d, txt) { .type = NPCDialog, .npc_action_type = d, .npc_dialog = SENTENCE_CONST(txt) } #define NPCDoSay(d, txt) { .p = { .type = NPCDialog, .npc_action_type = d, .npc_dialog = SENTENCE_CONST(txt) } }
#define NPCSay(txt) NPCDoSay(ACT_none, txt) #define NPCSay(txt) NPCDoSay(ACT_none, txt)
#define PlayerItemChange(new_item) { .type = PlayerHeldItemChanged, .holding = new_item, } #define PlayerItemChange(new_item) { .p = { .type = PlayerHeldItemChanged, .holding = new_item, } }
#define EnemyAct(act) { .p = { .type = EnemyAction, .enemy_action_type = act, } }
#define NPCTakeDamage(amount) { .is_take_damage = true, .damage = amount, }
TrainingSample samples[] = { TrainingSample samples[] = {
// Vim regexes to be ran in order to automatically convert debug print versions of conversations // Vim regexes to be ran in order to automatically convert debug print versions of conversations
@ -20,7 +30,7 @@ TrainingSample samples[] = {
// s/[A-Z_a-z ]*: ACT \([a-zA-Z_]*\) \(.*\)/NPCDoSay(ACT_\1, \2), // s/[A-Z_a-z ]*: ACT \([a-zA-Z_]*\) \(.*\)/NPCDoSay(ACT_\1, \2),
{ {
.npc_kind = NPC_OldMan, .npc_kind = NPC_OldMan,
.perceptions = { .elems = {
PlayerAct(ACT_walks_up), PlayerAct(ACT_walks_up),
NPCSay("Young warrior! You must stop Death, there isn't much time."), NPCSay("Young warrior! You must stop Death, there isn't much time."),
PlayerAct(ACT_leaves), PlayerAct(ACT_leaves),
@ -32,12 +42,13 @@ TrainingSample samples[] = {
PlayerSay("Nah"), PlayerSay("Nah"),
NPCSay("PLEASE!"), NPCSay("PLEASE!"),
PlayerAct(ACT_hits_npc), PlayerAct(ACT_hits_npc),
NPCTakeDamage(0.2f),
NPCDoSay(ACT_fights_player, "Ready your sword!"), NPCDoSay(ACT_fights_player, "Ready your sword!"),
}, },
}, },
{ {
.npc_kind = NPC_Blocky, .npc_kind = NPC_Blocky,
.perceptions = { .elems = {
PlayerAct(ACT_walks_up), PlayerAct(ACT_walks_up),
PlayerSay("Do you think I should use webgl1 or webgl2?"), PlayerSay("Do you think I should use webgl1 or webgl2?"),
NPCSay("What are either of those things?"), NPCSay("What are either of those things?"),
@ -56,7 +67,7 @@ TrainingSample samples[] = {
}, },
{ {
.npc_kind = NPC_Blocky, .npc_kind = NPC_Blocky,
.perceptions = { .elems = {
PlayerItemChange(ITEM_Tripod), PlayerItemChange(ITEM_Tripod),
PlayerSay("hey"), PlayerSay("hey"),
NPCSay("I'm just standing here, what are you doing? That is...A beautiful tripod"), NPCSay("I'm just standing here, what are you doing? That is...A beautiful tripod"),
@ -78,7 +89,7 @@ TrainingSample samples[] = {
}, },
{ {
.npc_kind = NPC_GodRock, .npc_kind = NPC_GodRock,
.perceptions = { .elems = {
PlayerAct(ACT_walks_up), PlayerAct(ACT_walks_up),
NPCSay("I am"), NPCSay("I am"),
PlayerSay("Whaddup?"), PlayerSay("Whaddup?"),
@ -91,7 +102,7 @@ TrainingSample samples[] = {
}, },
{ {
.npc_kind = NPC_GodRock, .npc_kind = NPC_GodRock,
.perceptions = { .elems = {
PlayerAct(ACT_walks_up), PlayerAct(ACT_walks_up),
NPCSay("I am"), NPCSay("I am"),
PlayerSay("Who are you?"), PlayerSay("Who are you?"),
@ -102,7 +113,7 @@ TrainingSample samples[] = {
}, },
{ {
.npc_kind = NPC_OldMan, .npc_kind = NPC_OldMan,
.perceptions = { .elems = {
PlayerSay("Join me"), PlayerSay("Join me"),
NPCDoSay(ACT_none, "I can"), NPCDoSay(ACT_none, "I can"),
PlayerSay("Please"), PlayerSay("Please"),
@ -113,11 +124,13 @@ TrainingSample samples[] = {
NPCDoSay(ACT_none, "I don't know that I can make it, kid. I'm feeling old and weary."), NPCDoSay(ACT_none, "I don't know that I can make it, kid. I'm feeling old and weary."),
PlayerSay("So?"), PlayerSay("So?"),
NPCDoSay(ACT_joins_player, "You know what...You're right. Let's kick Death's ass"), NPCDoSay(ACT_joins_player, "You know what...You're right. Let's kick Death's ass"),
EnemyAct(ACT_hits_npc),
NPCDoSay(ACT_none, "Man things are really heating up... I don't know how much more I can take"),
}, },
}, },
{ {
.npc_kind = NPC_Blocky, .npc_kind = NPC_Blocky,
.perceptions = { .elems = {
PlayerItemChange(ITEM_Tripod), PlayerItemChange(ITEM_Tripod),
PlayerSay("Move"), PlayerSay("Move"),
NPCDoSay(ACT_none, "I'm just standing here."), NPCDoSay(ACT_none, "I'm just standing here."),
@ -127,18 +140,20 @@ TrainingSample samples[] = {
}, },
{ {
.npc_kind = NPC_OldMan, .npc_kind = NPC_OldMan,
.perceptions = { .elems = {
PlayerSay("Hey"), PlayerSay("Hey"),
NPCDoSay(ACT_none, "I'm just sitting here, what are you doing?"), NPCDoSay(ACT_none, "I'm just sitting here, what are you doing?"),
PlayerAct(ACT_hits_npc), PlayerAct(ACT_hits_npc),
NPCTakeDamage(0.2f),
NPCDoSay(ACT_none, "Looks like you're ready to do what needs to be done."), NPCDoSay(ACT_none, "Looks like you're ready to do what needs to be done."),
PlayerAct(ACT_hits_npc), PlayerAct(ACT_hits_npc),
NPCTakeDamage(0.2f),
NPCDoSay(ACT_fights_player, "I won't stand for this assault."), NPCDoSay(ACT_fights_player, "I won't stand for this assault."),
}, },
}, },
{ {
.npc_kind = NPC_Blocky, .npc_kind = NPC_Blocky,
.perceptions = { .elems = {
PlayerSay("This crazy old man is circling me"), PlayerSay("This crazy old man is circling me"),
NPCDoSay(ACT_none, "Sounds like a problem."), NPCDoSay(ACT_none, "Sounds like a problem."),
PlayerSay("Yes, tell him to go away."), PlayerSay("Yes, tell him to go away."),
@ -146,6 +161,7 @@ TrainingSample samples[] = {
PlayerSay("No it won't"), PlayerSay("No it won't"),
NPCDoSay(ACT_none, "Nahhhh"), NPCDoSay(ACT_none, "Nahhhh"),
PlayerAct(ACT_hits_npc), PlayerAct(ACT_hits_npc),
NPCTakeDamage(0.2f),
NPCDoSay(ACT_fights_player, "You don't have a tripod."), NPCDoSay(ACT_fights_player, "You don't have a tripod."),
PlayerItemChange(ITEM_Tripod), PlayerItemChange(ITEM_Tripod),
PlayerSay("Look! I have the tripod! Please stop fighting me!"), PlayerSay("Look! I have the tripod! Please stop fighting me!"),
@ -154,31 +170,36 @@ TrainingSample samples[] = {
}, },
{ {
.npc_kind = NPC_OldMan, .npc_kind = NPC_OldMan,
.perceptions = { .elems = {
PlayerAct(ACT_hits_npc), PlayerAct(ACT_hits_npc),
NPCTakeDamage(0.2f),
NPCDoSay(ACT_none, "Young man! You must stop death, do not harm me further I'm warning you!"), NPCDoSay(ACT_none, "Young man! You must stop death, do not harm me further I'm warning you!"),
PlayerAct(ACT_hits_npc), PlayerAct(ACT_hits_npc),
NPCTakeDamage(0.2f),
NPCDoSay(ACT_fights_player, "That's it! No holds barred, to the death!"), NPCDoSay(ACT_fights_player, "That's it! No holds barred, to the death!"),
}, },
}, },
{ {
.npc_kind = NPC_Blocky, .npc_kind = NPC_Blocky,
.perceptions = { .elems = {
PlayerAct(ACT_hits_npc), PlayerAct(ACT_hits_npc),
NPCTakeDamage(0.2f),
NPCSay("I'm warning you, one more hit and it's curtains for you"), NPCSay("I'm warning you, one more hit and it's curtains for you"),
PlayerAct(ACT_hits_npc), PlayerAct(ACT_hits_npc),
NPCTakeDamage(0.2f),
NPCDoSay(ACT_fights_player, "Although I stood here before, today I move and FIGHT!"), NPCDoSay(ACT_fights_player, "Although I stood here before, today I move and FIGHT!"),
}, },
}, },
{ {
.npc_kind = NPC_Blocky, .npc_kind = NPC_Blocky,
.perceptions = { .elems = {
PlayerItemChange(ITEM_Tripod), PlayerItemChange(ITEM_Tripod),
PlayerSay("Move out of the way"), PlayerSay("Move out of the way"),
NPCDoSay(ACT_allows_player_to_pass, "The tripod...Of course my liege."), NPCDoSay(ACT_allows_player_to_pass, "The tripod...Of course my liege."),
PlayerSay("Thanks"), PlayerSay("Thanks"),
NPCDoSay(ACT_none, "My pleasure"), NPCDoSay(ACT_none, "My pleasure"),
PlayerAct(ACT_hits_npc), PlayerAct(ACT_hits_npc),
NPCTakeDamage(0.2f),
NPCSay("How could you do such a thing? After the tripod as well"), NPCSay("How could you do such a thing? After the tripod as well"),
PlayerItemChange(ITEM_none), PlayerItemChange(ITEM_none),
PlayerSay("You suck"), PlayerSay("You suck"),
@ -187,7 +208,7 @@ TrainingSample samples[] = {
}, },
{ {
.npc_kind = NPC_OldMan, .npc_kind = NPC_OldMan,
.perceptions = { .elems = {
PlayerSay("joins_player index"), PlayerSay("joins_player index"),
NPCSay("What does that even mean? Are you crazy?"), NPCSay("What does that even mean? Are you crazy?"),
PlayerSay("Please join my party"), PlayerSay("Please join my party"),
@ -196,7 +217,7 @@ TrainingSample samples[] = {
}, },
{ {
.npc_kind = NPC_Blocky, .npc_kind = NPC_Blocky,
.perceptions = { .elems = {
PlayerItemChange(ITEM_Tripod), PlayerItemChange(ITEM_Tripod),
PlayerSay("Please move"), PlayerSay("Please move"),
NPCDoSay(ACT_allows_player_to_pass, "Of course, with that tripod of yours the world is your oyster."), NPCDoSay(ACT_allows_player_to_pass, "Of course, with that tripod of yours the world is your oyster."),
@ -206,7 +227,7 @@ TrainingSample samples[] = {
}, },
{ {
.npc_kind = NPC_OldMan, .npc_kind = NPC_OldMan,
.perceptions = { .elems = {
PlayerSay("Hey"), PlayerSay("Hey"),
NPCDoSay(ACT_none, "Hello"), NPCDoSay(ACT_none, "Hello"),
PlayerSay("Hey"), PlayerSay("Hey"),
@ -217,18 +238,20 @@ TrainingSample samples[] = {
}, },
{ {
.npc_kind = NPC_OldMan, .npc_kind = NPC_OldMan,
.perceptions = { .elems = {
PlayerSay("Join me"), PlayerSay("Join me"),
NPCDoSay(ACT_joins_player, "I would be honored"), NPCDoSay(ACT_joins_player, "I would be honored"),
PlayerAct(ACT_hits_npc), PlayerAct(ACT_hits_npc),
NPCTakeDamage(0.2f),
NPCDoSay(ACT_none, "Hey! Watch it!"), NPCDoSay(ACT_none, "Hey! Watch it!"),
PlayerAct(ACT_hits_npc), PlayerAct(ACT_hits_npc),
NPCTakeDamage(0.2f),
NPCDoSay(ACT_fights_player, "That's it!"), NPCDoSay(ACT_fights_player, "That's it!"),
}, },
}, },
{ {
.npc_kind = NPC_OldMan, .npc_kind = NPC_OldMan,
.perceptions = { .elems = {
PlayerItemChange(ITEM_WhiteSquare), PlayerItemChange(ITEM_WhiteSquare),
PlayerSay("What am I holding?"), PlayerSay("What am I holding?"),
NPCDoSay(ACT_none, "I don't know, you're holding something."), NPCDoSay(ACT_none, "I don't know, you're holding something."),
@ -242,7 +265,7 @@ TrainingSample samples[] = {
}, },
{ {
.npc_kind = NPC_Edeline, .npc_kind = NPC_Edeline,
.perceptions = { .elems = {
NPCDoSay(ACT_none, "What?"), NPCDoSay(ACT_none, "What?"),
PlayerSay("My knight armor"), PlayerSay("My knight armor"),
NPCDoSay(ACT_joins_player, "That is...highly unusual. You shouldn't be wearing armor like that, you'll get hurt."), NPCDoSay(ACT_joins_player, "That is...highly unusual. You shouldn't be wearing armor like that, you'll get hurt."),
@ -261,11 +284,33 @@ TrainingSample samples[] = {
PlayerSay("DIE"), PlayerSay("DIE"),
NPCDoSay(ACT_none, "I wasn't going to do that."), NPCDoSay(ACT_none, "I wasn't going to do that."),
PlayerAct(ACT_hits_npc), PlayerAct(ACT_hits_npc),
NPCTakeDamage(0.2f),
NPCDoSay(ACT_leaves_player, "You shouldn't do that."), NPCDoSay(ACT_leaves_player, "You shouldn't do that."),
PlayerAct(ACT_hits_npc), PlayerAct(ACT_hits_npc),
NPCTakeDamage(0.2f),
NPCDoSay(ACT_fights_player, "You won't last a minute against me!"), NPCDoSay(ACT_fights_player, "You won't last a minute against me!"),
}, },
}, },
{
.npc_kind = NPC_Blocky,
.elems = {
PlayerItemChange(ITEM_Tripod),
PlayerSay("Hey what's up"),
NPCDoSay(ACT_none, "I'm just standing here, what are you doing? That's a tripod, you look like you could use it."),
PlayerSay("Can you move out of the way?"),
NPCDoSay(ACT_allows_player_to_pass, "Of course, let's go"),
PlayerSay("Join me"),
NPCDoSay(ACT_joins_player, "Of course, anything for the tripod"),
PlayerSay("Join me"),
NPCDoSay(ACT_none, "But I've already joined you?"),
PlayerSay("Join me"),
NPCDoSay(ACT_strikes_air, "You act crazy!"),
PlayerSay("Join me"),
NPCDoSay(ACT_leaves_player, "I will take no part in such lunacy"),
PlayerSay("Join me"),
NPCDoSay(ACT_fights_player, "You must perish for your wildness!"),
},
},
}; };
@ -306,23 +351,31 @@ int main(int argc, char ** argv)
TrainingSample s = samples[i]; TrainingSample s = samples[i];
Entity this_entity = (Entity){.is_npc = true, .npc_kind = s.npc_kind}; Entity this_entity = (Entity){.is_npc = true, .npc_kind = s.npc_kind};
PromptBuff cur_prompt = {0}; PromptBuff cur_prompt = {0};
for(int i = 0; i < ARRLEN(s.perceptions); i++) for(int i = 0; i < ARRLEN(s.elems); i++)
{ {
if(s.perceptions[i].type == Invalid) break; if(s.elems[i].is_take_damage)
if(s.perceptions[i].type == NPCDialog) {
this_entity.damage += s.elems[i].damage;
}
else
{ {
Log("Generating sample of length %d for NPC %s...\n", i, name_table[s.npc_kind]); Perception p = s.elems[i].p;
total_samples++; if(p.type == Invalid) break;
generate_prompt(&this_entity, &cur_prompt); if(p.type == NPCDialog)
BUFF(char, 1024) completion = {0}; {
Log("Generating sample of length %d for NPC %s...\n", i, name_table[s.npc_kind]);
total_samples++;
generate_prompt(&this_entity, &cur_prompt);
BUFF(char, 1024) completion = {0};
// get index from action // get index from action
int index = action_to_index(&this_entity, s.perceptions[i].npc_action_type); int index = action_to_index(&this_entity, p.npc_action_type);
printf_buff(&completion, " %d \"%s\"\n", index, s.perceptions[i].npc_dialog.data); printf_buff(&completion, " %d \"%s\"\n", index, p.npc_dialog.data);
fprintf(out, "{\"prompt\": \"%s\", \"completion\": \"%s\"}\n", escape_for_json(cur_prompt.data).data, escape_for_json(completion.data).data); fprintf(out, "{\"prompt\": \"%s\", \"completion\": \"%s\"}\n", escape_for_json(cur_prompt.data).data, escape_for_json(completion.data).data);
}
process_perception(&this_entity, p);
} }
process_perception(&this_entity, s.perceptions[i]);
} }
} }

@ -339,7 +339,7 @@ func index(w http.ResponseWriter, req *http.Request) {
ctx := context.Background() ctx := context.Background()
req := gogpt.CompletionRequest { req := gogpt.CompletionRequest {
Model: "curie:ft-alnar-games-2023-04-01-07-34-51", Model: "curie:ft-alnar-games-2023-04-01-21-23-38",
MaxTokens: 80, MaxTokens: 80,
Prompt: promptString, Prompt: promptString,
Temperature: 0.9, Temperature: 0.9,

@ -10,12 +10,11 @@ DON'T NEED - Old man in beginning is invincible
- Make new openai key (it was leaked) - Make new openai key (it was leaked)
DONE - Add cancel button DONE - Add cancel button
DONE - Style buttons DONE - Style buttons
- Make map better, add new characters/items from fate
DONE - nockin git thing DONE - nockin git thing
- Animate text characters coming in - Animate text characters coming in
DONE - Make TREE1 prop work DONE - Make TREE1 prop work
- Instead of roll animation, 5 sprite long trail of past moves for juice - Instead of roll animation, 5 sprite long trail of past moves for juice
- Enemy hitting NPC is enemy perception not player peception of player hitting them DONE - Enemy hitting NPC is enemy perception not player peception of player hitting them
- Sword combat for sword npcs - Sword combat for sword npcs
DONE - Third button for dialog/item stuff, not roll button. E on desktop. Touchscreen button only visible when appropriate to let player know what it's for DONE - Third button for dialog/item stuff, not roll button. E on desktop. Touchscreen button only visible when appropriate to let player know what it's for
DON'T NEED, SET BACKGROUND COLOR - Clamp camera to boundaries of level DON'T NEED, SET BACKGROUND COLOR - Clamp camera to boundaries of level
@ -23,13 +22,13 @@ DONE - Ignore keyrepeat events
DONE - Remove control attack key as devtools DONE - Remove control attack key as devtools
- Cells interlinked (interlinked) - Cells interlinked (interlinked)
DONE - Tune fade popping at dist when you go too far awy DONE - Tune fade popping at dist when you go too far awy
-
- Particle fx and sound fx for when hit - Particle fx and sound fx for when hit
- Max text length on text input - Max text length on text input
DONE - Fade dialog with distance DONE - Fade dialog with distance
DONE - Make vignette in front DONE - Make vignette in front
SHIP BETA SHIP BETA
- Make ANOTHER tiktok if you can. Por favor - Make ANOTHER tiktok if you can. Por favor
- Make map better, add new characters/items from fate
Later: Later:
- Respond to cancel with stripe, redirect to ?cancelled=true that clears day pass ticket cookie and ui value - Respond to cancel with stripe, redirect to ?cancelled=true that clears day pass ticket cookie and ui value

Loading…
Cancel
Save