diff --git a/flight.rdbg b/flight.rdbg index ba90e93..4a0966e 100644 Binary files a/flight.rdbg and b/flight.rdbg differ diff --git a/gamestate.c b/gamestate.c index 76bb717..efd1f12 100644 --- a/gamestate.c +++ b/gamestate.c @@ -842,12 +842,17 @@ bool box_enterable(Entity *box) bool box_interactible(GameState *gs, Player *for_player, Entity *box) { + (void)for_player; // make sure to handle case where for_player is NULL if you end up using this variable flight_assert(box->is_box); if (box->box_type == BoxMerge) { return merge_box_is_merged(gs, box); } + else if (box->box_type == BoxLandingGear) + { + return box->sees_possible_landing || box->landed_constraint != NULL; + } else { return false; @@ -2738,6 +2743,10 @@ void process(struct GameState *gs, double dt) flight_assert(potential_seat->is_box); flight_assert(potential_seat->box_type == BoxMerge); } + if (potential_seat->box_type == BoxLandingGear) + { + potential_seat->toggle_landing = true; + } } } @@ -3498,6 +3507,7 @@ void process(struct GameState *gs, double dt) } if (cur_box->box_type == BoxLandingGear) { + cur_box->sees_possible_landing = false; // false by default, if codepath which binds it sees landing it is set to true cpVect landing_point = cpvadd(entity_pos(cur_box), cpvmult(box_facing_vector(cur_box), BOX_SIZE / 2.0)); Entity *must_have_shape = get_entity(gs, cur_box->shape_to_land_on); bool want_have_constraint = true; @@ -3510,11 +3520,13 @@ void process(struct GameState *gs, double dt) if (want_have_constraint) want_have_constraint &= cpvdist(entity_pos(must_have_shape), landing_point) < BOX_SIZE + LANDING_GEAR_MAX_DIST; + // maybe merge all codepaths that delete constraint into one somehow, but seems hard #define DELETE_CONSTRAINT(constraint) \ { \ cpSpaceRemoveConstraint(gs->space, constraint); \ cpConstraintFree(constraint); \ constraint = NULL; \ + cur_box->shape_to_land_on = (EntityID){0}; \ } if (want_have_constraint) { @@ -3531,6 +3543,10 @@ void process(struct GameState *gs, double dt) cpSpaceAddConstraint(gs->space, cur_box->landed_constraint); on_create_constraint(cur_box, cur_box->landed_constraint); } + if (cur_box->toggle_landing) + { + DELETE_CONSTRAINT(cur_box->landed_constraint); + } } else { @@ -3538,7 +3554,6 @@ void process(struct GameState *gs, double dt) { DELETE_CONSTRAINT(cur_box->landed_constraint); } - cur_box->shape_to_land_on = (EntityID){0}; // maybe see something to land on cpVect along = box_facing_vector(cur_box); @@ -3549,9 +3564,13 @@ void process(struct GameState *gs, double dt) cpShape *found = cpSpaceSegmentQueryFirst(gs->space, from, to, 0.0, FILTER_DEFAULT, &query_result); if (found != NULL && cpShapeGetBody(found) != box_grid(cur_box)->body) { - cur_box->shape_to_land_on = get_id(gs, cp_shape_entity(found)); + cur_box->sees_possible_landing = true; + if (cur_box->toggle_landing) + cur_box->shape_to_land_on = get_id(gs, cp_shape_entity(found)); } } + + cur_box->toggle_landing = false; // handle it } } } diff --git a/loaded/landing_gear_cant_land.png b/loaded/landing_gear_cant_land.png new file mode 100644 index 0000000..93c0003 Binary files /dev/null and b/loaded/landing_gear_cant_land.png differ diff --git a/loaded/landing_gear_could_land.png b/loaded/landing_gear_could_land.png new file mode 100644 index 0000000..8c842d5 Binary files /dev/null and b/loaded/landing_gear_could_land.png differ diff --git a/loaded/landing_gear_landed.png b/loaded/landing_gear_landed.png new file mode 100644 index 0000000..f111464 Binary files /dev/null and b/loaded/landing_gear_landed.png differ diff --git a/main.c b/main.c index e46d981..df2b559 100644 --- a/main.c +++ b/main.c @@ -138,7 +138,9 @@ static sg_image image_noenergy; static sg_image image_orb; static sg_image image_orb_frozen; static sg_image image_radardot; -static sg_image image_landing_gear; +static sg_image image_landing_gear_landed; +static sg_image image_landing_gear_could_land; +static sg_image image_landing_gear_cant_land; static sg_image image_pip; static sg_image image_enter_exit; @@ -857,7 +859,9 @@ static void init(void) image_orb = load_image("loaded/orb.png"); image_orb_frozen = load_image("loaded/orb_frozen.png"); image_radardot = load_image("loaded/radardot.png"); - image_landing_gear = load_image("loaded/landing_gear.png"); + image_landing_gear_landed = load_image("loaded/landing_gear_landed.png"); + image_landing_gear_could_land = load_image("loaded/landing_gear_could_land.png"); + image_landing_gear_cant_land = load_image("loaded/landing_gear_cant_land.png"); image_pip = load_image("loaded/pip.png"); image_enter_exit = load_image("loaded/enter_exit.png"); } @@ -1068,7 +1072,7 @@ static void ui(bool draw, double dt, double width, double height) { if (keypressed[SAPP_KEYCODE_ESCAPE].pressed) picking_new_boxtype = false; - if(picking_new_boxtype) + if (picking_new_boxtype) choosing_flags = false; AABB pick_modal = (AABB){ .x = width * 0.25, @@ -2400,6 +2404,21 @@ static void frame(void) if (get_entity(&gs, b->player_who_is_inside_of_me) != NULL) img = image_medbay_used; } + if (b->box_type == BoxLandingGear) + { + if (b->landed_constraint != NULL) + { + img = image_landing_gear_landed; + } + else if (box_interactible(&gs, myplayer(), b)) + { + img = image_landing_gear_could_land; + } + else + { + img = image_landing_gear_cant_land; + } + } if (b->box_type == BoxSolarPanel) { sgp_set_image(0, image_solarpanel_charging); @@ -2412,7 +2431,7 @@ static void frame(void) bool interactible = box_interactible(&gs, myplayer(), b); bool enterable = box_enterable(b); - if (myplayer() != NULL && interactible || enterable) + if ((myplayer() != NULL && interactible) || enterable) { if (box_has_point((BoxCentered){ .pos = entity_pos(b), @@ -2468,7 +2487,7 @@ static void frame(void) else { pipeline_scope(goodpixel_pipeline) - draw_texture_centered(entity_pos(b), BOX_SIZE); + draw_texture_centered(entity_pos(b), BOX_SIZE); } sgp_reset_image(0); @@ -2803,10 +2822,10 @@ void cleanup(void) server_info.should_quit = true; ma_mutex_unlock(&server_info.info_mutex); WaitForSingleObject(server_thread_handle, INFINITE); - + destroy(&gs); free(gs.entities); - + end_profiling_mythread(); end_profiling(); @@ -2818,7 +2837,7 @@ void cleanup(void) opus_encoder_destroy(enc); opus_decoder_destroy(dec); - + sgp_shutdown(); sg_shutdown(); enet_deinitialize(); @@ -2957,12 +2976,12 @@ sapp_desc sokol_main(int argc, char *argv[]) .window_title = "Flight Not Hosting", .icon.sokol_default = true, .event_cb = event, - #ifdef CONSOLE_CREATE +#ifdef CONSOLE_CREATE .win32_console_create = true, - #endif - #ifdef CONSOLE_ATTACH +#endif +#ifdef CONSOLE_ATTACH .win32_console_attach = true, - #endif +#endif .sample_count = 4, // anti aliasing }; } diff --git a/types.h b/types.h index ac2baf2..0071c0e 100644 --- a/types.h +++ b/types.h @@ -382,6 +382,8 @@ typedef struct Entity cpConstraint *landed_constraint; // when not null, landing gear landed on something. Only valid while shape_to_land_on is a valid reference // to land, set this to the shape to land on. A constraint will be created if it is valid. If it's not, it will be zerod EntityID shape_to_land_on; // checked for surface distance to make sure is valid + bool toggle_landing; // set when player commands landing gear to toggle landing state + bool sees_possible_landing; // set while processing, used to cosmetically show that the landing gear can be toggled PlatonicDetection detected_platonics[SCANNER_MAX_PLATONICS]; // intensity of 0.0 means undetected