@ -916,6 +916,7 @@ typedef struct Bone
struct Bone * parent ;
struct Bone * parent ;
Mat4 matrix_local ;
Mat4 matrix_local ;
Mat4 inverse_model_space_pos ;
Mat4 inverse_model_space_pos ;
MD_String8 name ;
float length ;
float length ;
} Bone ;
} Bone ;
@ -1096,6 +1097,8 @@ Armature load_armature(MD_Arena *arena, MD_String8 binary_file, MD_String8 armat
ser_bool ( & ser , & is_armature ) ;
ser_bool ( & ser , & is_armature ) ;
assert ( is_armature ) ;
assert ( is_armature ) ;
ser_MD_String8 ( & ser , & to_return . name , arena ) ;
MD_String8 image_filename ;
MD_String8 image_filename ;
ser_MD_String8 ( & ser , & image_filename , scratch . arena ) ;
ser_MD_String8 ( & ser , & image_filename , scratch . arena ) ;
arena - > align = 16 ; // SSE requires quaternions are 16 byte aligned
arena - > align = 16 ; // SSE requires quaternions are 16 byte aligned
@ -1113,6 +1116,7 @@ Armature load_armature(MD_Arena *arena, MD_String8 binary_file, MD_String8 armat
BlenderMat inverse_model_space_pose ;
BlenderMat inverse_model_space_pose ;
MD_i32 parent_index ;
MD_i32 parent_index ;
ser_MD_String8 ( & ser , & next_bone - > name , arena ) ;
ser_int ( & ser , & parent_index ) ;
ser_int ( & ser , & parent_index ) ;
ser_BlenderMat ( & ser , & model_space_pose ) ;
ser_BlenderMat ( & ser , & model_space_pose ) ;
ser_BlenderMat ( & ser , & inverse_model_space_pose ) ;
ser_BlenderMat ( & ser , & inverse_model_space_pose ) ;
@ -1273,7 +1277,7 @@ Room *get_cur_room(GameState *gs, ThreeDeeLevel *level)
Room * in_room = 0 ;
Room * in_room = 0 ;
for ( Room * cur = level - > room_list ; cur ; cur = cur - > next )
for ( Room * cur = level - > room_list ; cur ; cur = cur - > next )
{
{
if ( MD_S8Match ( cur - > name , gs - > current_room_name, 0 ) )
if ( MD_S8Match ( cur - > name , gs - > player- > current_room_name, 0 ) )
{
{
in_room = cur ;
in_room = cur ;
break ;
break ;
@ -2009,7 +2013,7 @@ Entity *new_entity(GameState *gs)
}
}
}
}
assert ( false ) ;
assert ( false ) ;
return NULL ;
return 0 ;
}
}
typedef struct ToVisit {
typedef struct ToVisit {
@ -2143,45 +2147,46 @@ Vec2 point_plane(Vec3 p)
# define parse_enumstr(arena, enum_str, errors, string_array, enum_kind_name, prefix) parse_enumstr_impl(arena, enum_str, string_array, ARRLEN(string_array), errors, enum_kind_name, prefix)
# define parse_enumstr(arena, enum_str, errors, string_array, enum_kind_name, prefix) parse_enumstr_impl(arena, enum_str, string_array, ARRLEN(string_array), errors, enum_kind_name, prefix)
ThreeDeeLevel level_threedee = { 0 } ;
void transition_to_room ( GameState * gs , ThreeDeeLevel * level , MD_String8 new_room_name )
{
Log ( " Transitioning to %.*s... \n " , MD_S8VArg ( new_room_name ) ) ;
assert ( gs ) ;
( void ) level ;
gs - > player - > current_room_name = new_room_name ;
}
void initialize_gamestate_from_threedee_level ( GameState * gs , ThreeDeeLevel * level )
void initialize_gamestate_from_threedee_level ( GameState * gs , ThreeDeeLevel * level )
{
{
memset ( gs , 0 , sizeof ( GameState ) ) ;
memset ( gs , 0 , sizeof ( GameState ) ) ;
rnd_gamerand_seed ( & gs - > random , RANDOM_SEED ) ;
rnd_gamerand_seed ( & gs - > random , RANDOM_SEED ) ;
// the target room will be whichever room has the player
// make entities for all rooms
bool found_player = false ;
for ( Room * cur_room = level - > room_list ; cur_room ; cur_room = cur_room - > next )
for ( Room * cur_room = level - > room_list ; cur_room ; cur_room = cur_room - > next )
{
{
for ( PlacedEntity * cur = cur_room - > placed_entity_list ; cur ; cur = cur - > next )
for ( PlacedEntity * cur = cur_room - > placed_entity_list ; cur ; cur = cur - > next )
{
if ( cur - > npc_kind = = NPC_Player )
{
gs - > current_room_name = cur_room - > name ;
break ;
}
}
if ( gs - > current_room_name . size > 0 ) break ;
}
Room * in_room = get_cur_room ( gs , level ) ;
bool found_player = false ;
for ( PlacedEntity * cur = in_room - > placed_entity_list ; cur ; cur = cur - > next )
{
{
Entity * cur_entity = new_entity ( gs ) ;
Entity * cur_entity = new_entity ( gs ) ;
cur_entity - > npc_kind = cur - > npc_kind ;
cur_entity - > npc_kind = cur - > npc_kind ;
cur_entity - > pos = point_plane ( cur - > t . offset ) ;
cur_entity - > pos = point_plane ( cur - > t . offset ) ;
cur_entity - > is_npc = true ;
cur_entity - > is_npc = true ;
if ( cur_entity - > npc_kind = = NPC_Player )
cur_entity - > current_room_name = cur_room - > name ;
if ( cur_entity - > npc_kind = = NPC_Player )
{
{
assert ( ! found_player ) ;
found_player = true ;
found_player = true ;
gs - > player = cur_entity ;
gs - > player = cur_entity ;
}
}
}
}
assert ( found_player ) ;
}
gs - > world_entity = new_entity ( gs ) ;
gs - > world_entity = new_entity ( gs ) ;
gs - > world_entity - > is_world = true ;
gs - > world_entity - > is_world = true ;
ENTITIES_ITER ( gs - > entities )
ENTITIES_ITER ( gs - > entities )
{
{
it - > rotation = PI32 ;
it - > rotation = PI32 ;
@ -2378,9 +2383,13 @@ void initialize_gamestate_from_threedee_level(GameState *gs, ThreeDeeLevel *leve
it - > perceptions_dirty = false ; // nobody should say anything about jester memories
it - > perceptions_dirty = false ; // nobody should say anything about jester memories
}
}
}
}
transition_to_room ( gs , & level_threedee , gs - > player - > current_room_name ) ;
}
}
ThreeDeeLevel level_threedee = { 0 } ;
void reset_level ( )
void reset_level ( )
{
{
@ -3304,6 +3313,7 @@ MD_String8 make_devtools_help(MD_Arena *arena)
P ( " 9 - instantly wins the game \n " ) ;
P ( " 9 - instantly wins the game \n " ) ;
P ( " P - toggles spall profiling on/off, don't leave on for very long as it consumes a lot of storage if you do that. The resulting spall trace is saved to the file '%s' \n " , PROFILING_SAVE_FILENAME ) ;
P ( " P - toggles spall profiling on/off, don't leave on for very long as it consumes a lot of storage if you do that. The resulting spall trace is saved to the file '%s' \n " , PROFILING_SAVE_FILENAME ) ;
P ( " If you hover over somebody it will display some parts of their memories, can be somewhat helpful \n " ) ;
P ( " If you hover over somebody it will display some parts of their memories, can be somewhat helpful \n " ) ;
P ( " P - immediately kills %s \n " , characters [ NPC_Raphael ] . name ) ;
# undef P
# undef P
MD_String8 to_return = MD_S8ListJoin ( arena , list , & ( MD_StringJoin ) { 0 } ) ;
MD_String8 to_return = MD_S8ListJoin ( arena , list , & ( MD_StringJoin ) { 0 } ) ;
@ -3380,7 +3390,7 @@ void init(void)
shifted_farmer_armature = load_armature ( persistent_arena , binary_file , MD_S8Lit ( " Farmer.bin " ) ) ;
shifted_farmer_armature = load_armature ( persistent_arena , binary_file , MD_S8Lit ( " Farmer.bin " ) ) ;
shifted_farmer_armature . image = image_shifted_farmer ;
shifted_farmer_armature . image = image_shifted_farmer ;
Log ( " Done. \n " ) ;
Log ( " Done. Used %f of the frame arena, %llu kB \n " , ( double ) frame_arena - > pos / ( double ) frame_arena - > cap , ( frame_arena - > pos / 1024 ) ) ;
MD_ArenaClear ( frame_arena ) ;
MD_ArenaClear ( frame_arena ) ;
@ -4642,7 +4652,7 @@ Vec2 move_and_slide(MoveSlideParams p)
{
{
ENTITIES_ITER ( gs . entities )
ENTITIES_ITER ( gs . entities )
{
{
if ( it ! = p . from & & ! ( it - > is_npc & & it - > dead ) & & ! it - > is_world )
if ( it ! = p . from & & ! ( it - > is_npc & & it - > dead ) & & ! it - > is_world & & MD_S8Match ( it - > current_room_name , p . from - > current_room_name , 0 ) )
{
{
BUFF_APPEND ( & to_check , ( ( CollisionObj ) { . circle . center = it - > pos , . circle . radius = entity_radius ( it ) , it } ) ) ;
BUFF_APPEND ( & to_check , ( ( CollisionObj ) { . circle . center = it - > pos , . circle . radius = entity_radius ( it ) , it } ) ) ;
}
}
@ -5875,7 +5885,7 @@ void frame(void)
ENTITIES_ITER ( gs . entities )
ENTITIES_ITER ( gs . entities )
{
{
if ( it - > is_npc )
if ( it - > is_npc & & MD_S8Match ( it - > current_room_name , gs . player - > current_room_name , 0 ) )
{
{
Transform draw_with = entity_transform ( it ) ;
Transform draw_with = entity_transform ( it ) ;
@ -6004,7 +6014,7 @@ void frame(void)
Entity * angel_entity = 0 ;
Entity * angel_entity = 0 ;
ENTITIES_ITER ( gs . entities )
ENTITIES_ITER ( gs . entities )
{
{
if ( it - > is_npc & & it - > npc_kind = = NPC_Angel )
if ( it - > is_npc & & it - > npc_kind = = NPC_Angel & & MD_S8Match ( it - > current_room_name , gs . player - > current_room_name , 0 ) )
{
{
assert ( ! angel_entity ) ;
assert ( ! angel_entity ) ;
angel_entity = it ;
angel_entity = it ;
@ -6096,7 +6106,7 @@ void frame(void)
draw_centered_text ( ( TextParams ) { false , mission_text , V2 ( screen_size ( ) . x * 0.5f , screen_size ( ) . y * 0.25f + vert ) , blendalpha ( WHITE , visible ) , mission_font_scale , . use_font = & font_for_text_input , . layer = LAYER_ANGEL_SCREEN } ) ;
draw_centered_text ( ( TextParams ) { false , mission_text , V2 ( screen_size ( ) . x * 0.5f , screen_size ( ) . y * 0.25f + vert ) , blendalpha ( WHITE , visible ) , mission_font_scale , . use_font = & font_for_text_input , . layer = LAYER_ANGEL_SCREEN } ) ;
if ( imbutton ( aabb_centered ( V2 ( screen_size ( ) . x / 2.0f , screen_size ( ) . y * 0.25f - vert ) , MulV2F ( V2 ( 170.0f , button_height ) , visible ) ) , visible , MD_S8Lit ( " Accept " ) , . layer = LAYER_ANGEL_SCREEN , . font = & font_for_text_input ) )
if ( imbutton ( aabb_centered ( V2 ( screen_size ( ) . x / 2.0f , screen_size ( ) . y * 0.25f - vert ) , MulV2F ( V2 ( 170.0f , button_height ) , visible ) ) , visible , MD_S8Lit ( " Accept " ) , . layer = LAYER_ANGEL_SCREEN , . font = & font_for_text_input ) )
{
{
Log( " Accepting mission... \n " ) ;
transition_to_room( & gs , & level_threedee , MD_S8Lit ( " Forest " ) ) ;
}
}
}
}
else
else
@ -6147,7 +6157,7 @@ void frame(void)
{
{
ENTITIES_ITER ( gs . entities )
ENTITIES_ITER ( gs . entities )
{
{
if ( it - > is_npc & & it - > npc_kind ! = NPC_Player )
if ( it - > is_npc & & it - > npc_kind ! = NPC_Player & & MD_S8Match ( it - > current_room_name , gs . player - > current_room_name , 0 ) )
{
{
if ( it - > undismissed_action )
if ( it - > undismissed_action )
{
{
@ -6917,7 +6927,7 @@ ISANERROR("Don't know how to do this stuff on this platform.")
else if ( it - > npc_kind = = NPC_Angel )
else if ( it - > npc_kind = = NPC_Angel )
{
{
action = " assign_gameplay_objective " ;
action = " assign_gameplay_objective " ;
action_argument = " KILL Dani el" ;
action_argument = " KILL Rapha el" ;
}
}
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 " ,
@ -6989,6 +6999,7 @@ ISANERROR("Don't know how to do this stuff on this platform.")
bool entity_talkable = true ;
bool entity_talkable = true ;
if ( entity_talkable ) entity_talkable = entity_talkable & & ( * it ) - > is_npc ;
if ( entity_talkable ) entity_talkable = entity_talkable & & ( * it ) - > is_npc ;
if ( entity_talkable ) entity_talkable = entity_talkable & & ( * it ) - > npc_kind ! = NPC_Player ;
if ( entity_talkable ) entity_talkable = entity_talkable & & ( * it ) - > npc_kind ! = NPC_Player ;
if ( entity_talkable ) entity_talkable = entity_talkable & & ! ( * it ) - > killed ;
# ifdef WEB
# ifdef WEB
if ( entity_talkable ) entity_talkable = entity_talkable & & ( * it ) - > gen_request_id = = 0 ;
if ( entity_talkable ) entity_talkable = entity_talkable & & ( * it ) - > gen_request_id = = 0 ;
# endif
# endif
@ -7089,7 +7100,45 @@ ISANERROR("Don't know how to do this stuff on this platform.")
pressed = before_gameplay_loops ;
pressed = before_gameplay_loops ;
// check if game objective has been fulfilled
{
if ( gs . no_angel_screen )
{
bool fulfilled = false ;
assert ( gs . assigned_objective ) ;
switch ( gs . objective . verb )
{
case KILL :
ENTITIES_ITER ( gs . entities )
{
if ( it - > npc_kind = = gs . objective . who_to_kill & & it - > killed )
{
fulfilled = true ;
break ;
}
}
break ;
}
if ( fulfilled )
{
gs . assigned_objective = false ;
transition_to_room ( & gs , & level_threedee , MD_S8Lit ( " StartingRoom " ) ) ;
}
}
}
# ifdef DEVTOOLS
# ifdef DEVTOOLS
if ( keypressed [ SAPP_KEYCODE_P ] )
{
ENTITIES_ITER ( gs . entities )
{
if ( it - > npc_kind = = NPC_Raphael )
{
it - > killed = true ;
}
}
}
if ( flycam )
if ( flycam )
{
{
Basis basis = flycam_basis ( ) ;
Basis basis = flycam_basis ( ) ;