Made MSVC crash again! Officially less stable than JAI, saving for posterity... Part of the way through adding aim/fire shotgun actions, and draw shotgun above characters when they're aiming at somebody

main
parent fc0c9e766d
commit abc81ba571

@ -21,6 +21,7 @@ typedef struct
} ActionInfo; } ActionInfo;
ActionInfo actions[] = { ActionInfo actions[] = {
#define NO_ARGUMENT .argument_description = "Takes no argument", .takes_argument = false #define NO_ARGUMENT .argument_description = "Takes no argument", .takes_argument = false
#define ARGUMENT(desc) .argument_description = desc, .takes_argument = true
{ {
.name = "none", .name = "none",
.description = "Do nothing", .description = "Do nothing",
@ -29,13 +30,23 @@ ActionInfo actions[] = {
{ {
.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",
.argument_description = "Expects the argument to be who you're joining", ARGUMENT("Expects the argument to be who you're joining"),
}, },
{ {
.name = "leave", .name = "leave",
.description = "Leave the party you're in right now", .description = "Leave the party you're in right now",
NO_ARGUMENT, NO_ARGUMENT,
}, },
{
.name = "aim_shotgun",
.description = "Aims your shotgun at the specified target, preparing you to fire at them and threatening their life.",
ARGUMENT("Expects the argument to be the name of the person you're aiming at, they must be nearby"),
},
{
.name = "fire_shotgun",
.description = "Fires your shotgun at the current target, killing the target.",
NO_ARGUMENT,
},
}; };
typedef enum typedef enum

@ -1644,17 +1644,23 @@ MD_String8 is_action_valid(MD_Arena *arena, Entity *from, Action a)
{ {
error_message = FmtWithLint(arena, "You can't join somebody, you're already in %s's party", characters[gete(from->joined)->npc_kind].name); error_message = FmtWithLint(arena, "You can't join somebody, you're already in %s's party", characters[gete(from->joined)->npc_kind].name);
} }
if(error_message.size == 0 && a.kind == ACT_fire_shotgun && gete(from->aiming_shotgun_at) == 0)
{
error_message = MD_S8Lit("You can't fire your shotgun without aiming it first");
}
if(error_message.size == 0 && a.kind == ACT_join) bool target_is_character = a.kind == ACT_join || a.kind == ACT_fire_shotgun;
if(error_message.size == 0 && target_is_character)
{ {
bool talk_to_valid = false; bool arg_valid = false;
BUFF_ITER(NpcKind, &talk) BUFF_ITER(NpcKind, &talk)
{ {
if(*it == a.argument.targeting) talk_to_valid = true; if(*it == a.argument.targeting) arg_valid = true;
} }
if(talk_to_valid == false) if(arg_valid == false)
{ {
error_message = FmtWithLint(arena, "Your action_argument for who to join, %s, is either invalid (you can't join nobody) or it's not an NPC that's near you right now.", characters[a.argument.targeting].name); error_message = FmtWithLint(arena, "Your action_argument for who this action should be directed at, %s, is either invalid (you can't operate on nobody) or it's not an NPC that's near you right now.", characters[a.argument.targeting].name);
} }
} }
@ -1719,6 +1725,12 @@ void cause_action_side_effects(Entity *from, Action a)
{ {
from->joined = (EntityRef){0}; from->joined = (EntityRef){0};
} }
if(a.kind == ACT_aim_shotgun)
{
Entity *target = get_targeted(from, a.argument.targeting);
assert(target); // error checked in is_action_valid
from->aiming_shotgun_at = frome(target);
}
MD_ReleaseScratch(scratch); MD_ReleaseScratch(scratch);
} }
@ -3084,6 +3096,7 @@ Armature *armatures[] = {
Mesh mesh_player = {0}; Mesh mesh_player = {0};
Mesh mesh_simple_worm = {0}; Mesh mesh_simple_worm = {0};
Mesh mesh_shotgun = {0};
void stbi_flip_into_correct_direction(bool do_it) void stbi_flip_into_correct_direction(bool do_it)
{ {
@ -3139,6 +3152,9 @@ void init(void)
binary_file = MD_LoadEntireFile(frame_arena, MD_S8Lit("assets/exported_3d/ExportedWithAnims.bin")); binary_file = MD_LoadEntireFile(frame_arena, MD_S8Lit("assets/exported_3d/ExportedWithAnims.bin"));
mesh_player = load_mesh(persistent_arena, binary_file, MD_S8Lit("ExportedWithAnims.bin")); mesh_player = load_mesh(persistent_arena, binary_file, MD_S8Lit("ExportedWithAnims.bin"));
binary_file = MD_LoadEntireFile(frame_arena, MD_S8Lit("assets/exported_3d/ShotgunMesh.bin"));
mesh_shotgun = load_mesh(persistent_arena, binary_file, MD_S8Lit("ShotgunMesh.bin"));
binary_file = MD_LoadEntireFile(frame_arena, MD_S8Lit("assets/exported_3d/ArmatureExportedWithAnims.bin")); binary_file = MD_LoadEntireFile(frame_arena, MD_S8Lit("assets/exported_3d/ArmatureExportedWithAnims.bin"));
player_armature = load_armature(persistent_arena, binary_file, MD_S8Lit("ArmatureExportedWithAnims.bin")); player_armature = load_armature(persistent_arena, binary_file, MD_S8Lit("ArmatureExportedWithAnims.bin"));
@ -3750,6 +3766,11 @@ Vec3 ray_intersect_plane(Vec3 ray_point, Vec3 ray_vector, Vec3 plane_point, Vec3
float d = DotV3(plane_point, MulV3F(plane_normal, -1.0f)); float d = DotV3(plane_point, MulV3F(plane_normal, -1.0f));
float denom = DotV3(plane_normal, ray_vector); float denom = DotV3(plane_normal, ray_vector);
if(fabsf(denom) <= 1e-4f)
{
// also could mean doesn't intersect plane
return plane_point;
}
assert(fabsf(denom) > 1e-4f); // avoid divide by zero assert(fabsf(denom) > 1e-4f); // avoid divide by zero
float t = -(DotV3(plane_normal, ray_point) + d) / DotV3(plane_normal, ray_vector); float t = -(DotV3(plane_normal, ray_point) + d) / DotV3(plane_normal, ray_vector);
@ -4690,13 +4711,18 @@ bool imbutton_key(AABB button_aabb, float text_scale, MD_String8 text, int key,
#define imbutton(...) imbutton_key(__VA_ARGS__, __LINE__, unwarped_dt, false) #define imbutton(...) imbutton_key(__VA_ARGS__, __LINE__, unwarped_dt, false)
Quat rot_on_plane_to_quat(float rot)
{
return QFromAxisAngle_RH(V3(0,1,0), AngleRad(-rot));
}
Transform entity_transform(Entity *e) Transform entity_transform(Entity *e)
{ {
// Models must face +X in blender. This is because, in the 2d game coordinate system, // Models must face +X in blender. This is because, in the 2d game coordinate system,
// a zero degree 2d rotation means you're facing +x, and this is how it is in the game logic. // a zero degree 2d rotation means you're facing +x, and this is how it is in the game logic.
// The rotation is negative for some reason that I'm not quite sure about though, something about // The rotation is negative for some reason that I'm not quite sure about though, something about
// the handedness of the 3d coordinate system not matching the handedness of the 2d coordinate system // the handedness of the 3d coordinate system not matching the handedness of the 2d coordinate system
Quat entity_rot = QFromAxisAngle_RH(V3(0,1,0), AngleRad(-e->rotation)); Quat entity_rot = rot_on_plane_to_quat(e->rotation);
return (Transform){.offset = AddV3(plane_point(e->pos), V3(0,0,0)), .rotation = entity_rot, .scale = V3(1, 1, 1)}; return (Transform){.offset = AddV3(plane_point(e->pos), V3(0,0,0)), .rotation = entity_rot, .scale = V3(1, 1, 1)};
/* /*
@ -5479,6 +5505,15 @@ void frame(void)
to_use->go_to_animation = MD_S8Lit("Idle"); to_use->go_to_animation = MD_S8Lit("Idle");
draw_thing((DrawnThing){.armature = to_use, .t = draw_with, .outline = gete(gs.player->interacting_with) == it}); draw_thing((DrawnThing){.armature = to_use, .t = draw_with, .outline = gete(gs.player->interacting_with) == it});
if(gete(it->aiming_shotgun_at))
{
Transform shotgun_t = draw_with;
shotgun_t.offset.y += 2.0f;
shotgun_t.scale = V3(3,3,3);
shotgun_t.rotation = rot_on_plane_to_quat(AngleOfV2(SubV2(gete(it->aiming_shotgun_at)->pos, it->pos)));
draw_thing((DrawnThing){.mesh = &mesh_shotgun, .t = shotgun_t});
}
} }
} }
} }
@ -6395,14 +6430,14 @@ ISANERROR("Don't know how to do this stuff on this platform.")
if (it->memories_last->context.talking_to_kind == it->npc_kind) if (it->memories_last->context.talking_to_kind == it->npc_kind)
//if (it->memories_last->context.author_npc_kind != it->npc_kind) //if (it->memories_last->context.author_npc_kind != it->npc_kind)
{ {
const char *action = "none"; const char *action = "aim_shotgun";
char *rigged_dialog[] = { char *rigged_dialog[] = {
"Repeated amounts of testing dialog overwhelmingly in support of the mulaney brothers", "Repeated amounts of testing dialog overwhelmingly in support of the mulaney brothers",
}; };
char *next_dialog = rigged_dialog[it->times_talked_to % ARRLEN(rigged_dialog)]; char *next_dialog = rigged_dialog[it->times_talked_to % ARRLEN(rigged_dialog)];
char *target = characters[it->memories_last->context.author_npc_kind].name; char *target = characters[it->memories_last->context.author_npc_kind].name;
target = characters[NPC_Player].name; target = characters[NPC_Player].name;
ai_response = FmtWithLint(frame_arena, "{\"target\": \"%s\", \"action\": \"%s\", \"speech\": \"%s\"}", target, action, next_dialog); ai_response = FmtWithLint(frame_arena, "{\"target\": \"%s\", \"action\": \"%s\", \"action_arg\": \"Raphael\", \"speech\": \"%s\"}", target, action, next_dialog);
#ifdef DESKTOP #ifdef DESKTOP
it->times_talked_to += 1; it->times_talked_to += 1;
#endif #endif
@ -6433,6 +6468,7 @@ ISANERROR("Don't know how to do this stuff on this platform.")
{ {
assert(succeeded); assert(succeeded);
assert(error_message.size == 0); assert(error_message.size == 0);
assert(is_action_valid(frame_arena, it, a));
perform_action(&gs, it, a); perform_action(&gs, it, a);
} }
else else

@ -229,6 +229,7 @@ typedef struct Entity
// npcs // npcs
NpcKind npc_kind; NpcKind npc_kind;
EntityRef joined; EntityRef joined;
EntityRef aiming_shotgun_at;
float target_rotation; // turns towards this angle in conversation float target_rotation; // turns towards this angle in conversation
bool being_hovered; bool being_hovered;
bool perceptions_dirty; bool perceptions_dirty;
@ -255,6 +256,9 @@ typedef struct Entity
int gen_request_id; int gen_request_id;
Vec2 target_goto; Vec2 target_goto;
// character // character
bool waiting_on_speech_with_somebody; bool waiting_on_speech_with_somebody;
EntityRef interacting_with; // for drawing outline on maybe interacting with somebody EntityRef interacting_with; // for drawing outline on maybe interacting with somebody
@ -316,6 +320,19 @@ void fill_available_actions(GameState *gs, Entity *it, AvailableActions *a)
{ {
BUFF_APPEND(a, ACT_join) BUFF_APPEND(a, ACT_join)
} }
bool has_shotgun = it->npc_kind == NPC_Daniel;
if(has_shotgun)
{
if(gete_specified(gs, it->aiming_shotgun_at))
{
BUFF_APPEND(a, ACT_fire_shotgun);
}
else
{
BUFF_APPEND(a, ACT_aim_shotgun);
}
}
} }
@ -408,6 +425,14 @@ MD_String8 generate_chatgpt_prompt(MD_Arena *arena, GameState *gs, Entity *e, Ca
// Needs better handling of when you leave, because the person you were following died. Maybe entities don't die anymore? // Needs better handling of when you leave, because the person you were following died. Maybe entities don't die anymore?
AddFmt("%s left their party\n", characters[it->context.author_npc_kind].name); AddFmt("%s left their party\n", characters[it->context.author_npc_kind].name);
} }
else if(it->action_taken == ACT_aim_shotgun)
{
AddFmt("%s aimed their shotgun at %s\n", characters[it->context.author_npc_kind].name, characters[it->action_argument.targeting].name);
}
else
{
assert(false);
}
} }
if(it->speech.text_length > 0) if(it->speech.text_length > 0)
{ {
@ -567,7 +592,10 @@ MD_String8 parse_chatgpt_response(MD_Arena *arena, Entity *e, MD_String8 action_
{ {
if(actions[out->kind].takes_argument) if(actions[out->kind].takes_argument)
{ {
if(out->kind == ACT_join) // @TODO refactor into, action argument kinds and they parse into different action argument types
bool arg_is_character = out->kind == ACT_join || out->kind == ACT_aim_shotgun;
if(arg_is_character)
{ {
bool found_npc = false; bool found_npc = false;
for(int i = 0; i < ARRLEN(characters); i++) for(int i = 0; i < ARRLEN(characters); i++)

@ -28,7 +28,7 @@
#ifdef DEVTOOLS #ifdef DEVTOOLS
// server url cannot have trailing slash // server url cannot have trailing slash
//#define MOCK_AI_RESPONSE #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