void wid_game_map_client_score_update (levelp level, uint8_t redo) { /* * Huge hack - we don't send ping/pong in single player mode, so * we don't get the level name. */ if (single_player_mode) { level = server_level; } if (!player) { return; } if (player->stats.pclass[0]) { wid_player_action_hide(true /* fast */, false /* player quit */); wid_player_action_visible(&player->stats, true /* fast */); } if (redo) { if (wid_scoreline_container_top) { wid_destroy(&wid_scoreline_container_top); } } uint8_t update; if (wid_scoreline_container_top) { update = true; } else { update = false; } /* * Create the area for the scores at the top. */ if (!update) { fpoint tl; fpoint br; tl.x = 0.7; tl.y = 0.0; br.x = 1.0; br.y = 1.0; wid_scoreline_container_top = wid_new_container(wid_game_map_client_window, "scoreline top"); wid_set_no_shape(wid_scoreline_container_top); wid_set_tl_br_pct(wid_scoreline_container_top, tl, br); wid_set_color(wid_scoreline_container_top, WID_COLOR_TL, BLACK); wid_set_color(wid_scoreline_container_top, WID_COLOR_BG, BLACK); wid_set_color(wid_scoreline_container_top, WID_COLOR_BR, BLACK); } double score_x = 0.78; double cash_x = 0.88; double player_y_offset = 0.17; // player start y double next_player_y_delta = 0.1; double score_and_cash_title_offset = 0.025; double score_and_cash_value_offset = 0.055; /* * Print the score. */ for (;;) { msg_player_state *p = client_get_player(); /* * Experience */ char tmp[20]; snprintf(tmp, sizeof(tmp), "%05u", p->stats.xp); static widp wid_score_container; if (!update) { wid_set_no_shape( wid_textbox(wid_scoreline_container_top, &wid_score, tmp, score_x, player_y_offset, med_font)); wid_score_container = wid_score; } else { wid_set_text(wid_score_container, tmp); wid_set_text_outline(wid_score_container, true); } /* * cash */ snprintf(tmp, sizeof(tmp), "%05u", p->stats.cash); static widp wid_cash_container; if (!update) { wid_set_no_shape( wid_textbox(wid_scoreline_container_top, &wid_cash, tmp, cash_x, player_y_offset, med_font)); wid_cash_container = wid_cash; } else { wid_set_text(wid_cash_container, tmp); wid_set_text_outline(wid_cash_container, true); } if (update) { break; } /* * Score title */ widp wid_score_title_container; wid_score_title_container = wid_textbox( wid_scoreline_container_top, &wid_score_title, "XP", score_x, player_y_offset - score_and_cash_title_offset, med_font); wid_set_no_shape(wid_score_title_container); /* * cash title */ widp wid_cash_title_container; wid_cash_title_container = wid_textbox( wid_scoreline_container_top, &wid_cash_title, "$$$", cash_x, player_y_offset - score_and_cash_title_offset, med_font); wid_set_no_shape(wid_cash_title_container); /* * Score title */ widp wid_name_title_container; char *name_title; /* * Just print the name, don't need the class as well. */ if (p->stats.pname[0]) { name_title = dynprintf("%%%%fg=cyan$%s", p->stats.pname); } else { name_title = 0; } wid_name_title_container = wid_textbox( wid_scoreline_container_top, &wid_name_title, name_title ? name_title : "No player", (score_x + cash_x) / 2, player_y_offset - score_and_cash_value_offset, med_font); if (name_title) { myfree(name_title); } wid_set_no_shape(wid_name_title_container); wid_set_color(wid_score, WID_COLOR_TEXT, RED); wid_set_color(wid_cash, WID_COLOR_TEXT, GOLD); wid_set_color(wid_score_title, WID_COLOR_TEXT, RED); wid_set_color(wid_cash_title, WID_COLOR_TEXT, GOLD); player_y_offset += next_player_y_delta; break; } if (update) { if (global_config.server_current_players > 1) { wid_raise(wid_chat_window); wid_visible(wid_chat_window, 0); } return; } /* * Print the level title. */ if (level_get_title(level) && strcasecmp(level_get_title(level), "(null)")) { widp wid_level_container; wid_level_container = wid_textbox(wid_scoreline_container_top, &wid_level, level_get_title(level), (score_x + cash_x) / 2.0, 0.02, med_font); wid_set_no_shape(wid_level_container); wid_set_color(wid_level, WID_COLOR_TEXT, WHITE); } /* * Print the level. */ if (client_level) { level_pos_t level_pos = level_get_level_pos(client_level); char *tmp = dynprintf("%%%%fg=green$Depth %d.%d", level_pos.y, level_pos.x); widp wid_level_container; wid_level_container = wid_textbox(wid_scoreline_container_top, &wid_level, tmp, (score_x + cash_x) / 2.0, 0.05, med_font); myfree(tmp); wid_set_no_shape(wid_level_container); wid_set_color(wid_level, WID_COLOR_TEXT, WHITE); } if (client_level) { uint32_t seed = level_get_seed(client_level); if (seed) { char *tmp = dynprintf("%%%%fg=green$Level %u", seed); widp wid_level_container; wid_level_container = wid_textbox(wid_scoreline_container_top, &wid_level, tmp, (score_x + cash_x) / 2.0, 0.08, med_font); myfree(tmp); wid_set_no_shape(wid_level_container); wid_set_color(wid_level, WID_COLOR_TEXT, WHITE); } } wid_raise(wid_scoreline_container_top); wid_update(wid_scoreline_container_top); wid_update_mouse(); wid_set_focus(wid_game_map_client_grid_container); if (global_config.server_current_players > 1) { wid_raise(wid_chat_window); wid_visible(wid_chat_window, 0); } }
/* * Replace or place a tile. */ widp wid_game_map_client_replace_tile (widp w, double x, double y, thingp t, tpp tp) { tree_rootp thing_tiles; const char *tilename; tilep tile; widp child; verify(w); /* * Grow tl and br to fit the template thing. Use the first tile. */ if (!tp) { tp = thing_tp(t); if (!tp) { ERR("no thing template to replace on client"); return (0); } } if ((x < 0) || (y < 0) || (x >= MAP_WIDTH) || (y >= MAP_WIDTH)) { LOG("client: thing template [%s] cannot be placed at %f %f", tp_short_name(tp), x, y); return (0); } thing_tiles = tp_get_tiles(tp); if (!thing_tiles) { ERR("thing template [%s] has no tiles", tp_short_name(tp)); return (0); } thing_tilep thing_tile; /* * Get a random tile to start with. */ thing_tile = (typeof(thing_tile)) thing_tile_random(thing_tiles); /* * Find the real tile that corresponds to this name. */ tilename = thing_tile_name(thing_tile); tile = tile_find(tilename); if (!tile) { ERR("tile name %s from thing %s not found on client", tilename, tp_short_name(tp)); return (0); } /* * Make a new thing. */ child = wid_new_square_button(wid_game_map_client_grid_container, "client map tile"); wid_set_mode(child, WID_MODE_NORMAL); wid_set_no_shape(child); /* * "paint" the thing. */ wid_game_map_client_set_thing_template(child, tp); if (!t) { t = thing_client_local_new(tp); } wid_set_thing(child, t); wid_set_tile(child, tile); double dx = 0; double dy = 0; /* * Does it appear as a different size on screen? */ double scale = tp_get_scale(tp); /* * So we have baby and bigger slimes. But alas this is visual only and has * no effect on hp on the server yet. */ if (thing_is_variable_size(t)) { scale += gaussrand(0.0, 0.05); } if (scale != 1.0) { wid_scaling_blit_to_pct_in(child, scale, scale, 500, 9999999); } if (thing_is_cloud_effect(t)) { /* * The epicenter needs to be where it was on the server as we do a * flood fill to see where the rest of the explosion goes. */ if (!t->is_epicenter) { dx = gaussrand(0.0, 0.5); dy = gaussrand(0.0, 0.5); } wid_fade_out(child, 1000); } thing_client_wid_update(t, x + dx, y + dy, false /* smooth */, true /* is new */); /* * Offset tall things */ if (scale != 1.0) { if (thing_is_blit_y_offset(t)) { wid_set_blit_y_offset(child, wid_get_height(child) * scale * -((scale - 1.0) / 2.0)); } } /* * If this is a pre-existing thing perhaps being recreated ona new level * then it will have a direction already. Update it. */ if (thing_is_animated(t)) { thing_animate(t); } /* * This adds it to the grid wid. */ #ifdef DEBUG_CLIENT_THING wid_update(child); char name[20]; sprintf(name, "%d",t->thing_id); wid_set_text(child,name); #endif /* * We've been told about the epicenter of an explsion, now emulate the * blast. */ if (t->is_epicenter && thing_is_cloud_effect(t) ) { if ((tp->id == THING_EXPLOSION1) || (tp->id == THING_EXPLOSION2) || (tp->id == THING_EXPLOSION3) || (tp->id == THING_EXPLOSION4) || (tp->id == THING_SMALL_EXPLOSION1) || (tp->id == THING_SMALL_EXPLOSION2) || (tp->id == THING_SMALL_EXPLOSION3) || (tp->id == THING_SMALL_EXPLOSION4) || (tp->id == THING_MED_EXPLOSION1) || (tp->id == THING_MED_EXPLOSION2) || (tp->id == THING_MED_EXPLOSION3) || (tp->id == THING_MED_EXPLOSION4) || (tp->id == THING_FIREBURST1) || (tp->id == THING_FIREBURST2) || (tp->id == THING_FIREBURST3) || (tp->id == THING_FIREBURST4) || (tp->id == THING_BOMB) || (tp->id == THING_POISON1) || (tp->id == THING_POISON2) || (tp->id == THING_CLOUDKILL1) || (tp->id == THING_CLOUDKILL2)) { level_place_explosion(client_level, 0, /* owner */ tp, t->x, t->y, t->x, t->y); } else { ERR("unknown explosion %s", thing_logname(t)); } } const char *sound = tp_sound_on_creation(tp); if (sound) { if (thing_is_cloud_effect(t)) { if (t->is_epicenter) { sound_play_at(sound, t->x, t->y); } } else { sound_play_at(sound, t->x, t->y); } } return (child); }
/* * Create the wid_text_input */ widp wid_large_text_input (const char *title, double x, double y, int32_t args, ...) { widp wid_text_input_container; widp wid_text_input_title; widp wid_text_input_window; widp wid_text_input_textbox; double title_h; uint32_t toth = 0; uint32_t maxbuttonw = 0; uint32_t maxbuttonh = 0; uint32_t button_y; va_list ap; const char *button_names[args]; double maxw; double maxh; wid_text_input_callback button_callback[args]; memset(button_callback, 0, sizeof(button_callback)); { double w; fontp font = large_font; ttf_text_size(&font, "TITLE", &w, &title_h, 0, 1.0f, 1.0f, false /* fixed width */); toth += title_h; } { fontp font = large_font; ttf_text_size(&font, "xxxxxxxxxxxxxxxx", &maxw, &maxh, 0, 1.0f, 1.0f, false /* fixed width */); } maxw = min(maxw, (uint32_t) ((game.video_gl_width * 3) / 4)); { int32_t n = args; while (n--) { button_names[n] = 0; } } { va_start(ap, args); int32_t n = args; while (n--) { button_names[args - n - 1] = va_arg(ap, const char*); button_callback[args - n - 1] = va_arg(ap, wid_text_input_callback); } va_end(ap); } { int32_t n = args; while (n--) { double w; double h; const char *button_name = button_names[n]; if (!button_name){ button_name = "<bug>"; } fontp font = med_font; ttf_text_size(&font, button_name, &w, &h, 0, 1.0f, 1.0f, false /* fixed width */); w += BUTTON_PAD_X; maxbuttonw = max(w, maxbuttonw); maxbuttonh = max(h, maxbuttonh); } } { wid_text_input_window = wid_new_rounded_window("wid_text_input"); wid_set_color(wid_text_input_window, WID_COLOR_TEXT, WHITE); color c = STEELBLUE2; c.a = 200; wid_set_color(wid_text_input_window, WID_COLOR_BG, c); c = STEELBLUE; c.a = 150; wid_set_color(wid_text_input_window, WID_COLOR_TL, c); wid_set_color(wid_text_input_window, WID_COLOR_BR, c); wid_set_bevel(wid_text_input_window, 4); fpoint tl = {0, 0}; fpoint br = {0, 0}; br.x += maxw; br.y += toth; br.y += toth; br.y += toth; br.x += PAD_X; /* * Space for input box. */ br.y += maxbuttonh; button_y = br.y; br.y += maxbuttonh; wid_set_tl_br(wid_text_input_window, tl, br); } if (title) { fpoint tl = {0, 0}; fpoint br = {0, 0}; br.x += maxw + PAD_X; br.y += title_h; tl.y += title_h/2; br.y += title_h/2; wid_text_input_title = wid_new_container(wid_text_input_window, "wid text_input container1"); wid_set_tl_br(wid_text_input_title, tl, br); wid_set_font(wid_text_input_title, large_font); wid_set_text(wid_text_input_title, title); } { fpoint tl = {0, 0}; fpoint br = {0, 0}; br.x = maxw; br.y += toth; tl.x += PAD_X/2; br.x += PAD_X/2; if (title) { /* * Add space for title. */ tl.y += title_h; br.y += title_h; } wid_text_input_container = wid_new_container(wid_text_input_window, wid_text_input_filelist_container_str); wid_set_tl_br(wid_text_input_container, tl, br); } { widp child; fpoint tl = {0.0f, 0.0f}; fpoint br = {0.0f, 0.0f}; tl.x = PAD_X / 2; tl.y = button_y - maxbuttonh - PAD_Y * 4; br.x = maxw + PAD_X / 2; br.y = tl.y + maxbuttonh * 4 - PAD_Y * 2; child = wid_new_square_button(wid_text_input_window, wid_text_input_filename_input_str); wid_set_color(child, WID_COLOR_BG, BLACK); wid_set_color(child, WID_COLOR_TL, STEELBLUE); wid_set_color(child, WID_COLOR_BR, STEELBLUE); color c; c = STEELBLUE2; wid_set_mode(child, WID_MODE_NORMAL); c.a = 100; wid_set_color(child, WID_COLOR_BG, c); wid_set_mode(child, WID_MODE_OVER); c.a = 50; wid_set_color(child, WID_COLOR_BG, c); wid_set_mode(child, WID_MODE_ACTIVE); c.a = 60; wid_set_color(child, WID_COLOR_BG, c); wid_set_mode(child, WID_MODE_NORMAL); wid_set_color(child, WID_COLOR_TEXT, GREEN); wid_set_tl_br(child, tl, br); wid_set_font(child, large_font); wid_set_text_outline(child, true); wid_set_on_key_down(child, wid_text_input_receive_input); wid_set_show_cursor(child, true); wid_set_focusable(child, args + 2); wid_text_input_textbox = child; } { int32_t x = 0; int32_t n = args; int32_t focus_order = args + 1; x += maxw; x += PAD_X/2; while (n--) { double w; double h; const char *button_name = button_names[n]; fontp font = med_font; ttf_text_size(&font, button_name, &w, &h, 0, 1.0f, 1.0f, false /* fixed width */); widp child; child = wid_new_rounded_small_button(wid_text_input_window, button_name); fpoint tl; fpoint br; tl.y = button_y; br.y = tl.y + maxbuttonh; br.x = x; tl.x = br.x - maxbuttonw; x = tl.x; x -= BUTTON_PAD_X; wid_set_tl_br(child, tl, br); wid_set_text(child, button_name); wid_set_font(child, med_font); color c; if (focus_order == 1) { c = GREEN; } else if (focus_order == 2) { c = STEELBLUE2; } else if (focus_order == 3) { c = CYAN; } else { c = GRAY; } wid_set_mode(child, WID_MODE_NORMAL); c.a = 100; wid_set_color(child, WID_COLOR_BG, c); wid_set_mode(child, WID_MODE_OVER); c.a = 250; wid_set_color(child, WID_COLOR_BG, c); wid_set_mode(child, WID_MODE_NORMAL); wid_set_focusable(child, focus_order--); wid_set_on_mouse_down(child, wid_text_input_button_event); wid_set_context(child, (void*)button_callback[n]); } } wid_move_to_pct_centered(wid_text_input_window, -2.5, y); wid_fade_in(wid_text_input_window, wid_fade_delay); wid_move_to_pct_centered_in(wid_text_input_window, x, y, wid_swipe_delay); wid_raise(wid_text_input_window); wid_focus_lock(wid_text_input_window); wid_update(wid_text_input_window); return (wid_text_input_textbox); }