#include "core/camera.h" #include "ents/item_placement.h" static bool build_submit_placements = false; static bool build_is_in_draw_mode = false; extern bool inv_is_inside; static uint8_t build_num_placements = 0; static item_placement build_placements[BUILD_MAX_PLACEMENTS] = {0}; bool build_is_deletion_mode = false; void buildmode_clear_buffers(void) { item_placement empty_placement = { .x = 0.0f, .y = 0.0f, .kind = -1 }; for (size_t i = 0; i < BUILD_MAX_PLACEMENTS; i++) { zpl_memcopy(&build_placements[i], &empty_placement, zpl_size_of(item_placement)); } } void buildmode_draw(void) { if (inv_is_inside) return; camera cam = camera_get(); camera old_cam = cam; entity_view *e = game_world_view_active_get_entity(cam.ent_id); if (!e) return; float zoom = renderer_zoom_get(); float mx = 0, my = 0; platform_get_block_realpos(&mx, &my); cam.x = (double)mx; cam.y = (double)my; // NOTE(zaklaus): Check distance double dx = old_cam.x - cam.x; double dy = old_cam.y - cam.y; double dsq = (dx*dx + dy*dy); bool is_outside_range = (dsq > zpl_square(WORLD_BLOCK_SIZE*14)); if (build_submit_placements) { build_submit_placements = false; buildmode_clear_buffers(); } if (IsKeyPressed(KEY_B)){ build_is_deletion_mode = !build_is_deletion_mode; } Item *item = &e->items[e->selected_item]; if (e->has_items && !e->inside_vehicle && item->quantity > 0 && (!is_outside_range || build_is_deletion_mode)) { item_usage usage = 0; uint16_t item_id = 0; if (!build_is_deletion_mode){ item_id = item_find(item->kind); usage = item_get_usage(item_id); } if (usage < UKIND_END_PLACE) { if (IsMouseButtonPressed(MOUSE_RIGHT_BUTTON) && !build_is_in_draw_mode) { build_is_in_draw_mode = true; build_num_placements = 0; buildmode_clear_buffers(); } uint32_t qty = BUILD_MAX_PLACEMENTS; bool directional = false; if (!build_is_deletion_mode){ directional = item_get_place_directional(item_id); qty = item->quantity; } world_block_lookup l = world_block_from_realpos((float)cam.x, (float)cam.y); if (build_is_deletion_mode && !l.is_outer){ goto build_skip_placements; } if (build_is_in_draw_mode) { for (size_t i = 0; i < BUILD_MAX_PLACEMENTS; i++) { item_placement *it = &build_placements[i]; if (it->kind == -1) { if (directional && build_num_placements > 2) { float p1x = build_placements[0].x; float p1y = build_placements[0].y; float p2x = build_placements[1].x; float p2y = build_placements[1].y; float p3x = (float)cam.x; float p3y = (float)cam.y; float sx = zpl_sign0(p2x-p1x); float sy = zpl_sign0(p2y-p1y); float sxx = zpl_sign0(p3x-p1x); float syy = zpl_sign0(p3y-p1y); if (sx != sxx || sy != syy) break; } it->x = (float)cam.x; it->y = (float)cam.y; it->kind = 0; build_num_placements++; break; } else if (it->x == (float)cam.x && it->y == (float)cam.y) { break; } } } if (!is_outside_range) renderer_draw_single((float)cam.x, (float)cam.y, ASSET_BUILDMODE_HIGHLIGHT, ColorAlpha(build_is_deletion_mode ? RED : WHITE, 0.2f)); build_skip_placements: build_num_placements = zpl_min(build_num_placements, qty); } } for (size_t i = 0; i < build_num_placements; i++) { item_placement *it = &build_placements[i]; renderer_draw_single(it->x, it->y, ASSET_BUILDMODE_HIGHLIGHT, ColorAlpha(build_is_deletion_mode ? RED : WHITE, 0.4f)); } if (build_is_in_draw_mode) { if (IsKeyPressed(KEY_SPACE)) { build_is_in_draw_mode = false; buildmode_clear_buffers(); } if (IsMouseButtonReleased(MOUSE_RIGHT_BUTTON)) { build_submit_placements = true; build_is_in_draw_mode = false; } } }