1
0
Fork 0
forked from NotAShelf/rogged

various: add admin build; various layout improvements

Signed-off-by: NotAShelf <raf@notashelf.dev>
Change-Id: Ieaa99fa0a32b42b1e97aada611d809b96a6a6964
This commit is contained in:
raf 2026-05-11 20:35:13 +03:00
commit 514a9560a2
Signed by: NotAShelf
GPG key ID: 29D95B64378DB4BF
9 changed files with 856 additions and 201 deletions

View file

@ -118,7 +118,9 @@ static void init_floor(GameState *gs, int floor_num) {
// Find spawn position
int start_x, start_y;
get_random_floor_tile(&gs->map, &start_x, &start_y, 100);
if (gs->map.room_count <= 0 || !get_room_floor_tile(&gs->map, &gs->map.rooms[0], &start_x, &start_y)) {
get_random_floor_tile(&gs->map, &start_x, &start_y, 100);
}
// Initialize player position if first floor
if (floor_num == 1) {
@ -148,6 +150,151 @@ static void init_floor(GameState *gs, int floor_num) {
gs->turn_count = 0;
}
#ifdef ROGGED_ADMIN_CONTROLS
static void admin_recompute_lighting(GameState *gs) {
LightSource player_light = {gs->player.position.x, gs->player.position.y, PLAYER_LIGHT_INTENSITY, PLAYER_LIGHT_RANGE};
LightSource sources[1 + 32];
sources[0] = player_light;
memcpy(sources + 1, gs->static_lights, gs->static_light_count * sizeof(LightSource));
compute_lighting(&gs->map, sources, 1 + gs->static_light_count);
}
static void admin_reveal_map(GameState *gs) {
for (int y = 0; y < MAP_HEIGHT; y++) {
for (int x = 0; x < MAP_WIDTH; x++) {
gs->map.remembered[y][x] = 1;
}
}
}
static void admin_apply_fullbright(GameState *gs) {
memset(gs->map.light_map, 255, sizeof(gs->map.light_map));
admin_reveal_map(gs);
}
static void admin_kill_enemies(GameState *gs) {
for (int i = 0; i < gs->enemy_count; i++) {
if (gs->enemies[i].alive) {
gs->enemies[i].alive = 0;
gs->enemies[i].hp = 0;
}
}
}
static void admin_teleport_to_stairs(GameState *gs) {
for (int y = 0; y < MAP_HEIGHT; y++) {
for (int x = 0; x < MAP_WIDTH; x++) {
if (gs->map.tiles[y][x] == TILE_STAIRS) {
gs->player.position.x = x;
gs->player.position.y = y;
gs->awaiting_descend = 1;
gs->last_message = "Admin: teleported to stairs";
gs->message_timer = 90;
admin_recompute_lighting(gs);
return;
}
}
}
}
static int admin_button(Rectangle rect, const char *label) {
Vector2 mouse = GetMousePosition();
int hovered = CheckCollisionPointRec(mouse, rect);
DrawRectangleRec(rect, hovered ? (Color){72, 62, 48, 235} : (Color){44, 42, 46, 235});
DrawRectangleLines((int)rect.x, (int)rect.y, (int)rect.width, (int)rect.height,
hovered ? (Color){210, 180, 110, 255} : (Color){112, 104, 92, 255});
DrawText(label, (int)rect.x + 8, (int)rect.y + 5, SMALL_FONT, (Color){235, 228, 210, 255});
return hovered && IsMouseButtonPressed(MOUSE_LEFT_BUTTON);
}
static void admin_controls(GameState *gs, int *visible, int *fullbright) {
if (IsKeyPressed(KEY_F1))
*visible = !*visible;
DrawRectangle(8, 8, 142, 22, (Color){10, 10, 12, 190});
DrawText("F1 Admin", 16, 13, SMALL_FONT, (Color){220, 190, 110, 255});
if (!*visible)
return;
const int x = 20;
const int start_y = 84;
const int w = 166;
const int h = 24;
const int gap = 8;
const int button_count = 10;
const int panel_padding_bottom = 16;
Rectangle panel = {8, 34, 190,
(float)(start_y - 34 + button_count * h + (button_count - 1) * gap + panel_padding_bottom)};
DrawRectangleRec(panel, (Color){12, 12, 15, 225});
DrawRectangleLines((int)panel.x, (int)panel.y, (int)panel.width, (int)panel.height, (Color){170, 145, 90, 255});
DrawText("Admin Controls", 20, 46, NORM_FONT, (Color){230, 205, 130, 255});
DrawText("development build only", 20, 62, TINY_FONT, (Color){170, 164, 150, 255});
int y = start_y;
if (admin_button((Rectangle){x, y, w, h}, "Heal full")) {
gs->player.hp = gs->player.max_hp;
gs->game_over = 0;
gs->last_message = "Admin: healed";
gs->message_timer = 60;
}
y += h + gap;
if (admin_button((Rectangle){x, y, w, h}, "+10 max HP")) {
gs->player.max_hp += 10;
gs->player.hp = gs->player.max_hp;
}
y += h + gap;
if (admin_button((Rectangle){x, y, w, h}, "+2 attack"))
gs->player.attack += 2;
y += h + gap;
if (admin_button((Rectangle){x, y, w, h}, "+2 defense"))
gs->player.defense += 2;
y += h + gap;
if (admin_button((Rectangle){x, y, w, h}, "Reveal map"))
admin_reveal_map(gs);
y += h + gap;
char fullbright_label[32];
snprintf(fullbright_label, sizeof(fullbright_label), "Fullbright: %s", *fullbright ? "on" : "off");
if (admin_button((Rectangle){x, y, w, h}, fullbright_label)) {
*fullbright = !*fullbright;
if (*fullbright) {
admin_apply_fullbright(gs);
} else {
admin_recompute_lighting(gs);
}
}
y += h + gap;
if (admin_button((Rectangle){x, y, w, h}, "Kill enemies"))
admin_kill_enemies(gs);
y += h + gap;
if (admin_button((Rectangle){x, y, w, h}, "Teleport stairs"))
admin_teleport_to_stairs(gs);
y += h + gap;
if (admin_button((Rectangle){x, y, w, h}, "Reroll floor")) {
init_floor(gs, gs->player.floor);
gs->last_message = "Admin: rerolled floor";
gs->message_timer = 60;
}
y += h + gap;
if (admin_button((Rectangle){x, y, w, h}, "Next floor")) {
int next_floor = gs->player.floor < NUM_FLOORS ? gs->player.floor + 1 : gs->player.floor;
init_floor(gs, next_floor);
gs->last_message = "Admin: advanced floor";
gs->message_timer = 60;
}
}
#endif
// Tick all status effects at the start of a turn
static void tick_all_effects(GameState *gs) {
// Player effects
@ -617,6 +764,10 @@ static void game_loop(unsigned int run_seed, FontManager *fm) {
SetExitKey(0);
int frame_counter = 0;
#ifdef ROGGED_ADMIN_CONTROLS
int admin_visible = 1;
int admin_fullbright = 0;
#endif
while (!WindowShouldClose()) {
frame_counter++;
@ -692,6 +843,11 @@ static void game_loop(unsigned int run_seed, FontManager *fm) {
if (gs.player.flash_timer > 0)
gs.player.flash_timer--;
#ifdef ROGGED_ADMIN_CONTROLS
if (admin_fullbright)
admin_apply_fullbright(&gs);
#endif
// Render
BeginDrawing();
ClearBackground(BLACK);
@ -744,6 +900,10 @@ static void game_loop(unsigned int run_seed, FontManager *fm) {
gs.final_score, gs.run_seed, fm);
}
#ifdef ROGGED_ADMIN_CONTROLS
admin_controls(&gs, &admin_visible, &admin_fullbright);
#endif
EndDrawing();
// small delay for key repeat control