Delete all previous characters and fighting state

main
parent 6d3594c6ad
commit 7316b9e974

@ -271,7 +271,7 @@ for o in D.objects:
collision_cubes.append((o.location, o.dimensions))
else:
if o.users_collection[0].name == 'Level':
print(f"Object {o.name} has mesh name {o.to_mesh().name} and image file {image_filename}")
print(f"Object {o.name} has mesh name {o.to_mesh().name}")
assert(o.rotation_euler.order == 'XYZ')
level_object_data.append(object_transform_info)
else:
@ -284,7 +284,7 @@ for o in D.objects:
assert(mesh_name != LEVEL_EXPORT_NAME)
output_filepath = bpy.path.abspath(f"//{EXPORT_DIRECTORY}/{mesh_name}.bin")
print(f"Exporting mesh to {output_filepath}")
print(f"Exporting mesh to {output_filepath} with image_filename {image_filename}")
with open(output_filepath, "wb") as f:
write_b8(f, False) # if it's an armature or not, first byte of the file
write_string(f, image_filename) # the image filename!

BIN
art/art.blend (Stored with Git LFS)

Binary file not shown.

@ -1,68 +1,2 @@
[
{can_hear: [NPC_Jester, NPC_Bill]},
{enum: NPC_Jester , dialog: "Hehehe! Quit quant, a peasant from the mortal realm!", to: Bill},
{enum: NPC_Bill , mood: Scared, dialog: "No...Please! Stay away from me! Who the Hell are you!", thoughts: "I'm kind of mad, and this Jester guy is kind of an asshole", to: Jester},
{enum: NPC_Jester , dialog: "Poor Bill, I'm sure your ex-wife says the same...", to: Bill},
{enum: NPC_Bill , mood: Angry, dialog: "You evil BASTARD!! What is this place???", thoughts: "I hate the Jester because he dissed my ex-wife. And, he's being all vague and condescending. I would punch him if I could", to: Jester},
{enum: NPC_Jester , dialog: "I'll leave that for you to find out ;)", action: ACT_causes_testicular_torsion, to: Bill},
{enum: NPC_Bill , mood: Agony, dialog: "AUGGHGHHH!!! THE PAIN IS UNBEARABLE", thoughts: "SCREW THIS JESTER GUY HE FUCKED WITH MY NUTS", to: Jester},
{enum: NPC_Jester , dialog: "That's just a taste of what's to come! Bye bye~", action: ACT_undoes_testicular_torsion, to: Bill},
{can_hear: [NPC_Jester, NPC_TheBlacksmith]},
{enum: NPC_Jester , dialog: "A fine strong man you are, mister meld!", to: TheBlacksmith},
{enum: NPC_TheBlacksmith, mood: Confused, dialog: "I'll take any complement I can get, but you suddenly knowing my name is pretty weird dude.", thoughts: "This Jester looking guy gives me the creeps...", to: Jester},
{enum: NPC_Jester , dialog: "A strong man needs strong metal...Some magic magnetic fish could do the trick! They'd pick up all the river iron", to: TheBlacksmith },
{enum: NPC_TheBlacksmith, mood: Curious, dialog: "You know what I'll bite, where do I get this fish.", thoughts: "I can't believe business is so poor that I'm stopping to this...", to: Jester},
{enum: NPC_Jester , dialog: "Come now, follow me...", to: TheBlacksmith},
{can_hear: [NPC_Jester, NPC_TheBlacksmith, NPC_Edeline]},
{enum: NPC_Jester , dialog: "Edeline, fine enchantress. This blacksmith has asked for your hand in marriage if you would enchant these fish for him", to: Edeline},
{enum: NPC_TheBlacksmith, mood: Anxious, dialog: "Y-yes...", thoughts: "THAT BASTARD! It'd be too awkward to back out now...", to: Edeline},
{enum: NPC_Edeline , mood: Happy, dialog: "Oh my gosh! I leap with joy! I see much joy in our future, Meld.", thoughts: "I really hope he doesn't back out, I'm tired of being the crazy town spinster!", to: Meld},
{enum: NPC_Jester , dialog: "The fish!", to: Edeline},
{enum: NPC_Edeline , mood: Curious, dialog: "AH! Of course, here you are then!", thoughts: "I have no idea what these magnetic fish would be good for...", action: "ACT_enchant_fish", to: Meld},
{enum: NPC_TheBlacksmith, mood: Happy, dialog: "Finally, maybe this will help me replenish my metal reserves", thoughts: "I have no idea where all my metal went. I wonder if somebody stole it", to: Edeline},
{can_hear: [NPC_Jester, NPC_Blue]},
{enum: NPC_Blue , mood: Angry, dialog: "What the-my rod! These fish broke my fishing rod! Why are they glowing???", thoughts: "I'll be destroyed in the free market if I don't figure this out!"},
{enum: NPC_Jester , dialog: "Ho-ho! You know, if you want your rod to get done in split, Meld's anvil's got plenty reserves...", to: Blue},
{enum: NPC_Blue , mood: Excited, dialog: "Are you saying I should steal, betray the trust of Meld, just so my company makes more money? Sold!", thoughts: "Meld's fault for not hiring private security!", to: Jester},
{can_hear: [NPC_Jester, NPC_Blue, NPC_TheBlacksmith]},
{enum: NPC_Blue , mood: Excited, dialog: "Hey meld, what's that shiny thing over there?", thoughts: "Time to steal me an iron pole for my iron ROD!", to: Meld},
{enum: NPC_TheBlacksmith, mood: Curious, dialog: "Hm?", thoughts: "What is it now....", to: Blue},
{can_hear: [NPC_Jester, NPC_Blue]},
{enum: NPC_Blue , mood: Happy, dialog: "Hehehe...", thoughts: "EASY!", action: "ACT_steal_iron_pole"},
{can_hear: [NPC_Jester, NPC_Blue, NPC_TheBlacksmith]},
{enum: NPC_TheBlacksmith, mood: Confused, dialog: "There wasn't anything over there?", thoughts: "What does this guy think he's doing?", to: Blue},
{enum: NPC_Blue , mood: Elated, dialog: "Don't worry about it man! You have a good one", thoughts: "PEACE OF CAKE!", to: TheBlacksmith},
{can_hear: [NPC_Jester, NPC_Davis]},
{enum: NPC_Jester , dialog: "You know Davis, I can promise you fortune and power beyond your comprehension if you assist me in my antics. I mean to bring devastation to this town", to: Davis},
{enum: NPC_Davis , mood: Sad, dialog: "...", speech: "This jester guy reminds me of when I was younger.", to: Jester},
{enum: NPC_Jester , dialog: "Cat got your tongue?", to: Davis},
{enum: NPC_Davis , mood: Angry, dialog: "You need friends so badly, mister jester, that you resort to disgusting party tricks and trivial annoyance? I will not allow this.", thoughts: "He can stare me down all he wants, all he'll find is a blank mirror.", to: Jester},
{enum: NPC_Jester , dialog: "Careful there, diogenes! I've got more knives than you fingers!", to: Davis},
{enum: NPC_Davis , mood: Indifferent, dialog: "Petty violence means nothing to me. Can't you see where you end? At nothing, where you began.", thoughts: "I am empty of everything.", to: Jester},
{enum: NPC_Jester , dialog: "Have it your way! I'll be in touch...", to: Davis},
{enum: NPC_Davis , mood: Confident, dialog: "If you bring me death, I welcome it. If you bring me victory, I am unperturbed. If you return, I will have your head, no matter the cost.", thoughts: "It really is a nice day out today.", to: Jester},
{can_hear: [NPC_Jester, NPC_Red]},
{enum: NPC_Jester , dialog: "Red, everybody in this town is a capitalist, and you must overthrow them!", to: Red},
{enum: NPC_Red , mood: Enraged, dialog: "What?? This is an OUTRAGE!", thoughts: "CAPITALIST PIGS!", to: Jester},
{can_hear: [NPC_Jester, NPC_TheKing]},
{enum: NPC_Jester , dialog: "Silly king, you think you have power? Your townsfolk are sure to revolt...", to: TheKing},
{enum: NPC_TheKing , mood: Scared, dialog: "This is unacceptable...you must tell me more.", thoughts: "If this jester lies I will destroy him.", to: Jester},
{enum: NPC_Jester , dialog: "Blue and Red are spouting free-will propaganda, tarnishing your position. Meld is disgusted by what your tarriffs impose on him, and Esmerelda fortells of doom and chaos to fall upon your kingdom.", to: TheKing},
{enum: NPC_TheKing , mood: Confident, dialog: "This is dire indeed...I will have to think on this. Thank you, Jester, for the warning.", thoughts: "I must remain calm and collected, even in the sightlines of such terrible danger to my kingdom.", to: Jester},
{can_hear: [NPC_Jester, NPC_Door]},
{enum: NPC_Jester , dialog: "Open, sesame!", to: Door},
{enum: NPC_Door , mood: Indifferent, dialog: "DENIED. SAY THE WORDS", to: Jester, thoughts: "I MUST PROTECT."},
{enum: NPC_Jester , dialog: "What words?", to: Door},
{enum: NPC_Door , mood: Indifferent, dialog: "UKNOWN. DATA PRIVATE", to: Jester, thoughts: "I MUST NEVER UTTER THE WORDS."},
{enum: NPC_Jester , dialog: "Cmon... don't want to spit it out?", to: Door},
{enum: NPC_Door , mood: Angry, dialog: "EVIL PRESENCE. DEFILE INNARDS, YOU WILL. DENIED. SAY THE WORDS", to: Jester, thoughts: "HE MUST NOT KNOW"},
{enum: NPC_Jester , dialog: "Ah! I've found all your secrets! The words are folly and temperance", to: Door},
{enum: NPC_Door , mood: Angry, dialog: "DENIED. ALL THREE ARE REQUIRED.", to: Jester, thoughts: "HE MUST HAVE ALL THREE"},
{can_hear: [NPC_Jester, NPC_Pile]},
{enum: NPC_Jester , dialog: "Now, for the almighty sword...", to: Pile},
{enum: NPC_Pile , dialog: "Your attempts are futile. I give the sword only to the great and honorable." to: Jester, thoughts: "I must retain the sword for the hero", mood: Confident}
]

@ -75,30 +75,6 @@ ActionInfo actions[] = {
.name = "leaves_player",
.description = "Leave the player",
},
{
.name = "fights_player",
.description = "Trap the player in conversation until you decide to stop fighting them",
},
{
.name = "stops_fighting_player",
.description = "Let the player go, and stop fighting them",
},
{
.name = "releases_sword_of_nazareth",
.description = "Give the player the sword of nazareth, releasing your grip and fulfilling your destiny",
},
{
.name = "opens_myself",
.description = "Open myself so that the player may enter. I must ONLY do this if the player utters the secret words " Scroll1_Secret ", " Scroll2_Secret ", and " Scroll3_Secret " in the same sentence.",
},
// Actions used by jester and other characters only in
// the prologue for the game
{ .name = "causes_testicular_torsion", },
{ .name = "undoes_testicular_torsion", },
{ .name = "enchant_fish", },
{ .name = "steal_iron_pole", },
{ .name = "knights_player", },
};
@ -114,43 +90,6 @@ ItemInfo items[] = {
.name = "Invalid",
.description = "There has been an internal error.",
},
{
.enum_name = "GoldCoin",
.name = "Gold Coin",
.description = "A bog-standard coin made out of gold, it's fairly valuable but nothing to cry about.",
},
{
.enum_name = "Chalice",
.name = "The Chalice of Gold",
.description = "A beautiful, glimmering chalice of gold. Some have said that drinking from it gives you eternal life.",
},
{
.enum_name = "Sword",
.name = "The Sword of Nazareth",
.description = "A powerful sword with heft, it inspires a fundamental glory",
},
{
.enum_name = "Idol",
.name = "Enriching Idol",
.description = "A glimmering emerald idol, its heft brings you dreams of vast wealth",
},
#define SCROLL_DESCRIPTION "An ancient, valuable scroll that says to 'use it' on the outside, but I'm not sure what that means. Who knows what secrets it contains?"
#define SCROLL_NAME "Ancient Scroll"
{
.enum_name = "Scroll1",
.name = SCROLL_NAME,
.description = SCROLL_DESCRIPTION,
},
{
.enum_name = "Scroll2",
.name = SCROLL_NAME,
.description = SCROLL_DESCRIPTION,
},
{
.enum_name = "Scroll3",
.name = SCROLL_NAME,
.description = SCROLL_DESCRIPTION,
},
};
typedef enum
@ -180,133 +119,11 @@ CharacterGen characters[] = {
.enum_name = "Invalid",
.prompt = "There has been an internal error.",
},
{
.name = "SimpleWorm",
.enum_name = "SimpleWorm",
.prompt = "There has been an internal error.",
},
{
.name = "Player",
.enum_name = "Player",
.prompt = "There has been an internal error.",
},
{
.name = "Jester",
.enum_name = "Jester",
.prompt = "He is evil and joy incarnate, The Jester has caused chaos so the player will listen. He writes his own dialog.",
},
{
#undef NPC_NAME
#define NPC_NAME "Red"
.name = NPC_NAME,
.enum_name = "Red",
.prompt = "He is dangerous and chaotic,an ardent communist who believes that the Proletariat must violently overthrow the ruling class. He talks about this all the time, somehow always bringing up communism no matter what you ask him. ",
},
{
#undef NPC_NAME
#define NPC_NAME "Pile of Rocks"
.name = NPC_NAME,
.enum_name = "Pile",
.prompt = "It is a pile of rocks, which holds the almighty Sword of Nazareth. It is sentient and can be conversed with for an unknown reason. It really doesn't want the player to take the Sword, because it's afraid of adventure. But, it can be convinced with effort to let go of the sword and give it to the player. Many many people have attempted to remove the sword via force throughout the ages, but none have succeeded.",
.writing_style = {
"Yes, I'm a pile of rocks. No, I don't know why.",
"This sword is all I have. Why would I give it away, for free?",
"I've been 'alive' (if you want to call it that) for 500 years.",
},
},
{
#undef NPC_NAME
#define NPC_NAME "Blue"
.name = NPC_NAME,
.enum_name = "Blue",
.prompt =
"He believes in the free market, and is a libertarian capitalist. He despises communists like Red, viewing them as destabalizing immature maniacs who don't get what's up with reality. Blue will always bring up libertarianism and its positives whenever you talk to him somehow. He's standing near the pile of rocks, which contains the sword of nazareth. Many warriors have tried to pull the sword from where it's embedded by force, but all have failed.",
.writing_style = {
"Yep! This here is 'The Pile' they call it around here.",
"No man has ever been able to get that sword yonder. Don't waste your time trying",
"The free market is the only thing that works!",
},
},
{
#undef NPC_NAME
#define NPC_NAME "Davis"
.name = NPC_NAME,
.enum_name = "Davis",
.prompt = "He has seen the end of all time and the void behind all things. He is despondent and brutal, having understood that everything withers and dies, just as it begins. The clash between his unending stark reality and the antics of the local blacksmith, Meld, and fortuneteller, Edeline, is crazy.",
.writing_style = {
"The end is nigh",
"No need to panic or fear, death awaits us all",
"Antics do not move me",
},
},
{
#undef NPC_NAME
#define NPC_NAME "Edeline"
.name = NPC_NAME,
.enum_name = "Edeline",
.prompt = "She is the town fortuneteller, sweet and kindhearted normally, but vile and ruthless to people who insult her or her magic. She specializes in a new 'Purple Magic' that Meld despises. Meld, the local blacksmith, thinks Edeline's magic is silly."
},
{
#undef NPC_NAME
#define NPC_NAME "Bill"
.name = NPC_NAME,
.enum_name = "Bill",
.prompt = "He's not from around this medieval fantasy land, instead " NPC_NAME " is a divorced car insurance accountant from Philadelphia with a receding hairline in his mid 40s. He lives in a one bedroom studio and his kids don't talk to him. " NPC_NAME " is terrified and will immediately insist on joining the player's party via the action 'joins_player' upon meeting them.",
.writing_style = {
"What the FUCK is going on here man!",
"Listen here, I don't have time for any funny business",
"I've gotta get back to my wife",
},
},
#undef NPC_NAME
#define NPC_NAME "Meld"
{
.name = NPC_NAME,
.enum_name = "TheBlacksmith",
.prompt = "He is a jaded blue collar worker from magic New Jersey who hates everything new, like Purple Magic, which Edeline, the local fortuneteller, happens to specialize in. He is cold, dry, and sarcastic, wanting money and power above anything else.\n",
},
{
#undef NPC_NAME
#define NPC_NAME "The King"
.name = NPC_NAME,
.enum_name = "TheKing",
.prompt = "He is a calm, honorable, eccentric ruler, who does the best he can to do good by his people, even if they can be a little crazy at times. Behind him stands an ancient door he has no idea how to open.",
.writing_style = {
"Here ye, here ye! I am the king of all that is naughty AND nice.",
"Hm? That door? Not sure what it is, but it is creepy!",
"I'll do what I can.",
"There's not much to do around here.",
},
},
{
#undef NPC_NAME
#define NPC_NAME "Offensive Arrow"
.name = NPC_NAME,
.enum_name = "Arrow",
.prompt = "It is a spiked arrow designd to insult and deride the player, with a specific insult. It will fight them until the player denies and rejects the insult, at which point it stops fighting.",
.writing_style = {
"You are quite the stinker!",
"I won't back down until you deny the allegations.",
"Quite an odd stance, you have.",
"Refute my insult, or stay perpetually in battle.",
},
},
{
#undef NPC_NAME
#define NPC_NAME "Ancient Door"
.name = NPC_NAME,
.enum_name = "Door",
.prompt = "It is an ancient door that only opens if the player says a sentence with all the three ancient passcode words in it: " Scroll1_Secret ", " Scroll2_Secret ", and " Scroll3_Secret ". It will NEVER tell the player these words, and barely says anything to the player, other than 'SAY THE WORDS'. It accepts no trade other than the player saying those three words. You always talk mysteriously and in all caps. Your purpose, as The Door, is to protect what is behind you with your entire being. This is why you must never utter the words, and only open when all of the words have been said.",
.writing_style = {
"SAY THE WORDS.",
"DENIED. SAY THE WORDS.",
"I AM LOOKING FOR THE ONE WHO KNOWS. SAY THE WORDS.",
"THERE WILL BE NO TRADE. THE ONLY THING OF VALUE TO ME ARE THE WORDS.",
"YOU HAVE SAID THE WORDS, AND NOW I OPEN.",
},
},
};
typedef struct

337
main.c

@ -644,32 +644,9 @@ Vec2 entity_aabb_size(Entity *e)
return V2(1.0f*0.9f, 1.0f*0.5f);
}
else if (e->is_npc)
{
if (npc_is_knight_sprite(e))
{
return V2(1.0f*0.5f, 1.0f*0.5f);
}
else if (e->npc_kind == NPC_Pile)
{
return V2(1.0f, 1.0f);
}
else if (e->npc_kind == NPC_Door)
{
return V2(1.0f*2.0f, 1.0f*2.0f);
}
else if (e->npc_kind == NPC_Arrow)
{
return V2(1.0f*2.0f, 1.0f*2.0f);
}
else if (e->npc_kind == NPC_SimpleWorm)
{
return V2(1.0f, 1.0f);
}
else
{
assert(false);
return (Vec2) { 0 };
}
return V2(0,0);
}
else if (e->is_prop)
{
@ -1572,12 +1549,6 @@ Entity *gete(EntityRef ref)
}
}
bool is_fighting(Entity *player)
{
assert(player->is_character);
return gete(player->talking_to) && gete(player->talking_to)->standing == STANDING_FIGHTING;
}
void push_memory(Entity *e, Memory new_memory)
{
new_memory.tick_happened = gs.tick;
@ -1687,32 +1658,6 @@ MD_String8 is_action_valid(MD_Arena *arena, Entity *from, Action a)
}
}
if(error_message.size == 0 && from->npc_kind == NPC_Door)
{
MD_String8 speech_str = MD_S8(a.speech, a.speech_length);
MD_String8 secrets[] = { MD_S8Lit(Scroll1_Secret), MD_S8Lit(Scroll2_Secret), MD_S8Lit(Scroll3_Secret) };
ARR_ITER(MD_String8, secrets)
{
if(MD_S8FindSubstring(speech_str, *it, 0, MD_StringMatchFlag_CaseInsensitive) != speech_str.size)
{
error_message = FmtWithLint(arena, "You can't say the word '%.*s', it would spoil your secret to the player", MD_S8VArg(*it));
}
}
}
if(error_message.size == 0 && a.kind == ACT_releases_sword_of_nazareth)
{
if(error_message.size == 0 && from->npc_kind != NPC_Pile)
{
error_message = FmtWithLint(arena, "Only the pile of rocks can give away the sword of nazareth");
}
if(error_message.size == 0 && from->gave_away_sword)
{
error_message = FmtWithLint(arena, "You don't have the sword anymore, so you can't give it away");
}
}
if(error_message.size == 0 && a.kind == ACT_gift_item_to_targeting)
{
assert(a.argument.item_to_give >= 0 && a.argument.item_to_give < ARRLEN(items));
@ -1795,17 +1740,6 @@ void cause_action_side_effects(Entity *from, Action a)
assert(to);
}
if(a.kind == ACT_releases_sword_of_nazareth)
{
assert(from->npc_kind == NPC_Pile);
from->gave_away_sword = true;
}
if(a.kind == ACT_opens_myself)
{
assert(from->npc_kind == NPC_Door);
from->opened = true;
}
if(a.kind == ACT_gift_item_to_targeting)
{
@ -1834,18 +1768,7 @@ void cause_action_side_effects(Entity *from, Action a)
}
}
if(a.kind == ACT_fights_player)
{
from->standing = STANDING_FIGHTING;
gs.player->talking_to = frome(from);
gs.player->state = CHARACTER_TALKING;
assert(is_fighting(gs.player));
}
if(a.kind == ACT_stops_fighting_player && from->npc_kind == NPC_Arrow)
{
from->destroy = true;
}
if(a.kind == ACT_stops_fighting_player || a.kind == ACT_leaves_player)
if(a.kind == ACT_leaves_player)
{
from->standing = STANDING_INDIFFERENT;
}
@ -1908,49 +1831,6 @@ 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});
}
else if(item_is_scroll(kind))
{
showing_secret_str = scroll_secret(kind);
showing_secret_alpha = 1.0f;
}
}
// only called when the action is instantiated, correctly propagates the information
// of the action physically and through the party
// If the action is invalid, remembers the error if it's an NPC, and does nothing else
@ -2208,28 +2088,6 @@ void initialize_gamestate_from_threedee_level(GameState *gs, ThreeDeeLevel *leve
gs->world_entity = new_entity(gs);
gs->world_entity->is_world = true;
#ifdef DEVTOOLS
if(false)
{
for (int i = 0; i < 20; i++)
BUFF_APPEND(&gs->player->held_items, ITEM_GoldCoin);
}
ENTITIES_ITER(gs->entities)
{
if(false)
if (it->npc_kind == NPC_TheBlacksmith)
{
Memory test_memory = {0};
test_memory.context.author_npc_kind = NPC_TheBlacksmith;
MD_String8 speech = MD_S8Lit("This is some very important testing dialog. Too important to count. Very very very very important. Super caliafradgalisticexpelaladosis");
memcpy(test_memory.speech, speech.str, speech.size);
test_memory.speech_length = (int)speech.size;
push_memory(it, test_memory);
}
}
#endif
// parse and enact the drama document
if(1)
@ -2300,10 +2158,7 @@ void initialize_gamestate_from_threedee_level(GameState *gs, ThreeDeeLevel *leve
PushWithLint(scratch.arena, &drama_errors, "Current thought's speech is of size %d, bigger than allowed size %d", (int)thoughts_str.size, (int)ARRLEN(current_action.internal_monologue));
}
if(current_context.author_npc_kind != NPC_Jester)
{
current_action.mood = parse_enumstr(scratch.arena, mood_str, &drama_errors, moods, "MoodKind", "");
}
if(drama_errors.node_count == 0)
{
@ -2979,8 +2834,9 @@ void do_parsing_tests()
MD_ArenaTemp scratch = MD_GetScratch(0, 0);
/*
Entity e = {0};
e.npc_kind = NPC_TheBlacksmith;
e.npc_kind = NPC_Meld;
e.exists = true;
Action a = {0};
MD_String8 error;
@ -3027,6 +2883,7 @@ void do_parsing_tests()
assert(error.size == 0);
error = is_action_valid(scratch.arena, &e, a);
assert(error.size > 0);
*/
MD_ReleaseScratch(scratch);
}
@ -3131,8 +2988,8 @@ void init(void)
binary_file = MD_LoadEntireFile(frame_arena, MD_S8Lit("assets/exported_3d/level.bin"));
level_threedee = load_level(persistent_arena, binary_file);
binary_file = MD_LoadEntireFile(frame_arena, MD_S8Lit("assets/exported_3d/DecimatedPlayer.bin"));
mesh_player = load_mesh(persistent_arena, binary_file, MD_S8Lit("DecimatedPlayer.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"));
binary_file = MD_LoadEntireFile(frame_arena, MD_S8Lit("assets/exported_3d/ArmatureExportedWithAnims.bin"));
armature = load_armature(persistent_arena, binary_file, MD_S8Lit("ArmatureExportedWithAnims.bin"));
@ -4308,7 +4165,7 @@ Vec2 move_and_slide(MoveSlideParams p)
{
ENTITIES_ITER(gs.entities)
{
if (!(it->is_character && it->is_rolling) && it != p.from && !(it->is_npc && it->dead) && !it->is_world && !it->is_item && !(it->is_npc && it->npc_kind == NPC_Door && it->opened))
if (!(it->is_character && it->is_rolling) && it != p.from && !(it->is_npc && it->dead) && !it->is_world && !it->is_item)
{
BUFF_APPEND(&to_check, ((CollisionObj){aabb_centered(it->pos, entity_aabb_size(it)), it}));
}
@ -4846,27 +4703,7 @@ bool imbutton_key(AABB button_aabb, float text_scale, MD_String8 text, int key,
void draw_item(ItemKind kind, AABB in_aabb, float alpha)
{
Quad drawn = quad_aabb(in_aabb);
if (kind == ITEM_Chalice)
{
draw_quad((DrawParams) { drawn, IMG(image_chalice), blendalpha(WHITE, alpha), .layer = LAYER_UI_FG });
}
else if (kind == ITEM_GoldCoin)
{
draw_quad((DrawParams) { drawn, IMG(image_gold_coin), blendalpha(WHITE, alpha), .layer = LAYER_UI_FG });
}
else if (kind == ITEM_Sword)
{
draw_quad((DrawParams) { drawn, IMG(image_sword), blendalpha(WHITE, alpha), .layer = LAYER_UI_FG });
}
else if (item_is_scroll(kind))
{
draw_quad((DrawParams) { drawn, IMG(image_scroll), blendalpha(WHITE, alpha), .layer = LAYER_UI_FG });
}
else
{
assert(false);
}
}
Transform entity_transform(Entity *e)
@ -5616,32 +5453,6 @@ 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)
@ -5862,7 +5673,7 @@ void frame(void)
// A* code
if(false)
if (it->standing == STANDING_FIGHTING || it->standing == STANDING_JOINED)
if (it->standing == STANDING_JOINED)
{
Entity *targeting = gs.player;
@ -6143,44 +5954,6 @@ void frame(void)
*/
}
// @Place(NPC processing)
else if(it->npc_kind == NPC_Arrow)
{
if(it->standing == STANDING_INDIFFERENT)
{
CollisionInfo info = {0};
Vec2 movement = V2(ARROW_SPEED * dt, 0);
it->pos = move_and_slide((MoveSlideParams){it, it->pos, movement, .col_info_out = &info});
if(info.happened)
{
Entity *from = it;
BUFF_ITER(Entity *, &info.with)
{
if((*it)->is_character || ((*it)->is_npc && (*it)->standing == STANDING_JOINED))
{
Action fighting_action = {0};
fighting_action.kind = ACT_fights_player;
MD_String8 insult = MD_S8Fmt(frame_arena, "Ahaha! %s", arrow_insults[rand() % ARRLEN(arrow_insults)]);
memcpy(fighting_action.speech, insult.str, insult.size);
fighting_action.speech_length = (int)insult.size;
fighting_action.talking_to_somebody = true;
fighting_action.talking_to_kind = NPC_Player;
perform_action(from, fighting_action);
break;
}
}
if(from->standing != STANDING_FIGHTING)
{
// hit something, but didn't hit a fightable thing, or couldn't fight a fightable thing it hit
from->destroy = true;
}
}
}
}
else if(it->npc_kind == NPC_Door)
{
if(it->opened) it->opened_amount = Lerp(it->opened_amount, dt*5.0f, 1.0f);
}
else
{
}
@ -6218,15 +5991,6 @@ void frame(void)
{
if(it->machine_kind == MACH_arrow_shooter)
{
it->arrow_timer += dt;
if(it->arrow_timer >= SECONDS_PER_ARROW)
{
it->arrow_timer = 0.0;
Entity *new_arrow = new_entity(&gs);
new_arrow->is_npc = true;
new_arrow->npc_kind = NPC_Arrow;
new_arrow->pos = AddV2(it->pos, V2(entity_aabb_size(new_arrow).x + 0.01f, 0.0));
}
}
}
else if (it->is_world)
@ -6299,42 +6063,8 @@ void frame(void)
bool succeeded = true; // couldn't get AI response if false
if(mocking_the_ai_response)
{
if(false)
{
const char *argument = 0;
MD_String8List dialog_elems = {0};
ActionKind act = ACT_none;
it->times_talked_to++;
if(it->npc_kind == NPC_TheBlacksmith && it->standing != STANDING_JOINED)
{
assert(it->times_talked_to == 1);
act = ACT_joins_player;
PushWithLint(scratch.arena, &dialog_elems, "Joining you...");
}
else
{
PushWithLint(scratch.arena, &dialog_elems, "%d times talked", it->times_talked_to);
}
MD_StringJoin join = {0};
MD_String8 dialog = MD_S8ListJoin(scratch.arena, dialog_elems, &join);
if (argument)
{
ai_response = FmtWithLint(scratch.arena, "ACT_%s(%s) \"%.*s\"", actions[act].name, argument, MD_S8VArg(dialog));
}
else
{
ai_response = FmtWithLint(scratch.arena, "ACT_%s \"%.*s\"", actions[act].name, MD_S8VArg(dialog));
}
}
else
{
//ai_response = MD_S8Lit(" Within the player's party, while the player is talking to Meld, you hear: ACT_none \"Better have a good reason for bothering me. fjdskfjdsakfjsdakf\"");
ai_response = MD_S8Fmt(frame_arena, "{who_i_am: \"%s\", talking_to: nobody, action: joins_player, thoughts: \"I'm thinking...\", mood: Happy}", characters[it->npc_kind].name);
}
}
else
{
MD_String8 post_request_body = FmtWithLint(scratch.arena, "|%.*s", MD_S8VArg(prompt_str));
@ -6453,11 +6183,8 @@ void frame(void)
{
// don't add extra stuff to be done when changing state because in several
// places it's assumed to end dialog I can just do player->state = CHARACTER_IDLE
if(!is_fighting(gs.player))
{
gs.player->state = CHARACTER_IDLE;
}
}
else if (closest_interact_with)
{
if(closest_interact_with->is_machine)
@ -6474,15 +6201,6 @@ void frame(void)
members_in_party += 1;
}
}
if(members_in_party >= 3)
{
BUFF_APPEND(&gs.player->held_items, ITEM_Idol);
closest_interact_with->has_given_idol = true;
}
else
{
closest_interact_with->idol_reminder_opacity = 1.0f;
}
}
}
}
@ -6499,11 +6217,6 @@ void frame(void)
}
}
if(is_fighting(gs.player))
{
gs.player->state = CHARACTER_TALKING;
}
float speed = 0.0f;
{
Vec2 target_vel = { 0 };
@ -6751,39 +6464,11 @@ 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_rotated_centered(cur->from,V2(radius, radius), powf(cur->progress * 4.0f, 1.5f));
draw_quad((DrawParams){ to_draw, IMG(image_swipe), blendalpha(WHITE, 1.0f - cur->progress)});
}
}
}
PROFILE_SCOPE("secrets")
{
const float bottom_padding = 100.0f;
if(showing_secret_alpha > 0.0f)
{
showing_secret_alpha -= dt/5.0f;
}
draw_centered_text((TextParams){ false, MD_S8Fmt(frame_arena, "Scroll Secret: %.*s", MD_S8VArg(showing_secret_str)), V2(screen_size().x/2.0f, bottom_padding), blendalpha(WHITE, showing_secret_alpha), 2.0f});
}
PROFILE_SCOPE("dialog menu") // big dialog panel draw big dialog panel
{
static float on_screen = 0.0f;
Entity *talking_to = gete(gs.player->talking_to);
on_screen = Lerp(on_screen, unwarped_dt*9.0f, talking_to ? 1.0f : 0.0f);
if(is_fighting(gs.player))
{
assert(talking_to);
draw_centered_text((TextParams){ false, MD_S8Fmt(frame_arena, "%s is fighting you. You can't leave until they stop fighting you", characters[talking_to->npc_kind].name), V2(screen_size().x*0.75f, screen_size().y*0.5f), WHITE, 1.0f});
}
{
float panel_width = screen_size().x * 0.4f * on_screen;
AABB panel_aabb = (AABB) { .upper_left = V2(0.0f, screen_size().y), .lower_right = V2(panel_width, 0.0f) };
@ -6791,7 +6476,7 @@ void frame(void)
if (aabb_is_valid(panel_aabb))
{
if (!item_grid_state.open && pressed.mouse_down && !has_point(panel_aabb, mouse_pos) && !is_fighting(gs.player))
if (!item_grid_state.open && pressed.mouse_down && !has_point(panel_aabb, mouse_pos))
{
gs.player->state = CHARACTER_IDLE;
}
@ -7033,7 +6718,7 @@ void frame(void)
}
else
{
use_item(gs.player, selected_item);
// could put code here to use an item
}
}
}

@ -11,8 +11,6 @@
#include "tuning.h"
// TODO do strings: https://pastebin.com/Kwcw2sye
#define DO_CHATGPT_PARSING
#define Log(...) { printf("%s Log %d | ", __FILE__, __LINE__); printf(__VA_ARGS__); }
@ -168,7 +166,6 @@ typedef enum
{
STANDING_INDIFFERENT,
STANDING_JOINED,
STANDING_FIGHTING,
} NPCPlayerStanding;
@ -324,69 +321,11 @@ typedef struct Entity
typedef BUFF(NpcKind, 32) CanTalkTo;
bool npc_is_knight_sprite(Entity *it)
{
return it->is_npc && (false
|| it->npc_kind == NPC_Edeline
|| it->npc_kind == NPC_TheKing
|| it->npc_kind == NPC_TheBlacksmith
|| it->npc_kind == NPC_Red
|| it->npc_kind == NPC_Blue
|| it->npc_kind == NPC_Davis
|| it->npc_kind == NPC_Bill
|| it->npc_kind == NPC_Jester
);
}
bool item_is_scroll(ItemKind i)
{
if(i == ITEM_Scroll1 || i == ITEM_Scroll2 || i == ITEM_Scroll3)
{
return true;
}
else
{
return false;
}
}
MD_String8 scroll_secret(ItemKind i)
{
if(i == ITEM_Scroll1)
{
return MD_S8Lit(Scroll1_Secret);
}
else if(i == ITEM_Scroll2)
{
return MD_S8Lit(Scroll2_Secret);
}
else if(i == ITEM_Scroll3)
{
return MD_S8Lit(Scroll3_Secret);
}
else
{
assert(false);
return MD_S8Lit("");
}
}
float entity_max_damage(Entity *e)
{
return 1.0f;
}
bool npc_attacks_with_sword(Entity *it)
{
return false;
}
bool npc_attacks_with_shotgun(Entity *it)
{
return it->is_npc && (false);
}
typedef BUFF(ActionKind, 8) AvailableActions;
void fill_available_actions(Entity *it, AvailableActions *a)
@ -394,40 +333,18 @@ void fill_available_actions(Entity *it, AvailableActions *a)
*a = (AvailableActions) { 0 };
BUFF_APPEND(a, ACT_none);
if(it->npc_kind == NPC_Pile)
{
if(!it->gave_away_sword) BUFF_APPEND(a, ACT_releases_sword_of_nazareth);
}
else if(it->npc_kind == NPC_Door)
{
if(!it->opened) BUFF_APPEND(a, ACT_opens_myself);
}
else
{
if(it->held_items.cur_index > 0)
{
BUFF_APPEND(a, ACT_gift_item_to_targeting);
}
if (it->npc_kind == NPC_TheKing)
{
BUFF_APPEND(a, ACT_knights_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_stops_fighting_player);
}
}
}
@ -615,10 +532,6 @@ MD_String8 generate_chatgpt_prompt(MD_Arena *arena, Entity *e, CanTalkTo can_tal
{
standing_string = "You have joined the player, and are following them everywhere they go! This means you're on their side.";
}
else if (e->standing == STANDING_FIGHTING)
{
standing_string = "You are fighting the player right now! That means that the player can't leave conversation with you until you stop fighting them, effectively trapping the player with you.";
}
else
{
assert(false);

Loading…
Cancel
Save