2019-05-04 10:43:37 +00:00
|
|
|
mod bag;
|
2019-05-07 05:40:03 +00:00
|
|
|
mod buttons;
|
|
|
|
mod chat;
|
2020-07-14 20:11:39 +00:00
|
|
|
mod crafting;
|
2019-05-03 16:56:18 +00:00
|
|
|
mod esc_menu;
|
2020-07-12 00:39:50 +00:00
|
|
|
mod group;
|
2020-04-11 06:33:06 +00:00
|
|
|
mod hotbar;
|
2019-05-07 05:40:03 +00:00
|
|
|
mod img_ids;
|
2019-10-09 19:28:05 +00:00
|
|
|
mod item_imgs;
|
2019-05-07 05:40:03 +00:00
|
|
|
mod map;
|
2019-05-07 17:50:53 +00:00
|
|
|
mod minimap;
|
2020-05-24 06:37:10 +00:00
|
|
|
mod overhead;
|
2020-07-29 13:21:12 +00:00
|
|
|
mod overitem;
|
2020-05-14 16:56:10 +00:00
|
|
|
mod popup;
|
2019-05-07 05:40:03 +00:00
|
|
|
mod settings_window;
|
|
|
|
mod skillbar;
|
2020-04-06 15:25:45 +00:00
|
|
|
mod slots;
|
2019-08-07 13:14:26 +00:00
|
|
|
mod social;
|
|
|
|
mod spell;
|
2020-07-18 00:05:28 +00:00
|
|
|
mod util;
|
2019-04-26 20:24:05 +00:00
|
|
|
|
2020-02-06 17:34:32 +00:00
|
|
|
use crate::{ecs::comp::HpFloaterList, hud::img_ids::ImgsRot, ui::img_ids::Rotations};
|
2020-06-16 13:55:37 +00:00
|
|
|
pub use hotbar::{SlotContents as HotbarSlotContents, State as HotbarState};
|
|
|
|
|
2019-07-26 02:28:53 +00:00
|
|
|
pub use settings_window::ScaleChange;
|
2019-12-30 12:16:35 +00:00
|
|
|
use std::time::Duration;
|
2019-07-26 02:28:53 +00:00
|
|
|
|
2019-05-04 10:43:37 +00:00
|
|
|
use bag::Bag;
|
|
|
|
use buttons::Buttons;
|
2019-05-07 05:40:03 +00:00
|
|
|
use chat::Chat;
|
2019-09-01 19:04:03 +00:00
|
|
|
use chrono::NaiveTime;
|
2020-07-14 20:11:39 +00:00
|
|
|
use crafting::Crafting;
|
2019-05-03 16:56:18 +00:00
|
|
|
use esc_menu::EscMenu;
|
2020-07-12 00:39:50 +00:00
|
|
|
use group::Group;
|
2019-05-07 05:40:03 +00:00
|
|
|
use img_ids::Imgs;
|
2019-10-09 19:28:05 +00:00
|
|
|
use item_imgs::ItemImgs;
|
2019-05-07 05:40:03 +00:00
|
|
|
use map::Map;
|
2019-05-07 17:50:53 +00:00
|
|
|
use minimap::MiniMap;
|
2020-05-14 16:56:10 +00:00
|
|
|
use popup::Popup;
|
2019-07-23 01:02:57 +00:00
|
|
|
use serde::{Deserialize, Serialize};
|
2019-06-02 02:17:36 +00:00
|
|
|
use settings_window::{SettingsTab, SettingsWindow};
|
2019-05-07 05:40:03 +00:00
|
|
|
use skillbar::Skillbar;
|
2019-08-07 13:14:26 +00:00
|
|
|
use social::{Social, SocialTab};
|
|
|
|
use spell::Spell;
|
2019-03-15 04:55:52 +00:00
|
|
|
|
|
|
|
use crate::{
|
2020-01-10 00:33:38 +00:00
|
|
|
ecs::comp as vcomp,
|
2020-01-17 23:43:18 +00:00
|
|
|
i18n::{i18n_asset_key, LanguageMetadata, VoxygenLocalization},
|
2020-01-19 03:58:25 +00:00
|
|
|
render::{AaMode, CloudMode, Consts, FluidMode, Globals, Renderer},
|
2020-02-29 03:59:11 +00:00
|
|
|
scene::camera::{self, Camera},
|
2020-04-04 07:13:51 +00:00
|
|
|
ui::{fonts::ConrodVoxygenFonts, slot, Graphic, Ingameable, ScaleMode, Ui},
|
2019-07-26 02:28:53 +00:00
|
|
|
window::{Event as WinEvent, GameInput},
|
2019-04-20 18:08:39 +00:00
|
|
|
GlobalState,
|
2019-03-15 04:55:52 +00:00
|
|
|
};
|
2020-06-02 02:42:26 +00:00
|
|
|
use client::Client;
|
2020-06-12 07:43:20 +00:00
|
|
|
use common::{assets::load_expect, comp, sync::Uid, terrain::TerrainChunk, vol::RectRasterableVol};
|
2019-03-15 04:55:52 +00:00
|
|
|
use conrod_core::{
|
2019-07-05 16:21:11 +00:00
|
|
|
text::cursor::Index,
|
2020-06-03 17:59:09 +00:00
|
|
|
widget::{self, Button, Image, Text},
|
2019-05-07 05:40:03 +00:00
|
|
|
widget_ids, Color, Colorable, Labelable, Positionable, Sizeable, Widget,
|
2019-03-15 04:55:52 +00:00
|
|
|
};
|
2019-11-30 06:41:20 +00:00
|
|
|
use specs::{Join, WorldExt};
|
2020-06-04 07:11:35 +00:00
|
|
|
use std::{
|
|
|
|
collections::{HashMap, VecDeque},
|
|
|
|
time::Instant,
|
|
|
|
};
|
2019-05-15 00:04:58 +00:00
|
|
|
use vek::*;
|
2019-03-15 04:55:52 +00:00
|
|
|
|
2019-04-30 20:43:55 +00:00
|
|
|
const XP_COLOR: Color = Color::Rgba(0.59, 0.41, 0.67, 1.0);
|
2019-04-26 20:24:05 +00:00
|
|
|
const TEXT_COLOR: Color = Color::Rgba(1.0, 1.0, 1.0, 1.0);
|
2020-07-14 20:11:39 +00:00
|
|
|
const TEXT_GRAY_COLOR: Color = Color::Rgba(0.5, 0.5, 0.5, 1.0);
|
|
|
|
const TEXT_DULL_RED_COLOR: Color = Color::Rgba(0.56, 0.2, 0.2, 1.0);
|
2020-03-26 21:22:21 +00:00
|
|
|
const TEXT_BG: Color = Color::Rgba(0.0, 0.0, 0.0, 1.0);
|
2020-07-12 00:39:50 +00:00
|
|
|
const TEXT_COLOR_GREY: Color = Color::Rgba(1.0, 1.0, 1.0, 0.5);
|
2019-10-23 19:40:45 +00:00
|
|
|
const MENU_BG: Color = Color::Rgba(0.0, 0.0, 0.0, 0.4);
|
2019-10-04 18:27:12 +00:00
|
|
|
//const TEXT_COLOR_2: Color = Color::Rgba(0.0, 0.0, 0.0, 1.0);
|
2019-08-07 13:14:26 +00:00
|
|
|
const TEXT_COLOR_3: Color = Color::Rgba(1.0, 1.0, 1.0, 0.1);
|
2020-07-12 18:59:18 +00:00
|
|
|
const TEXT_BIND_CONFLICT_COLOR: Color = Color::Rgba(1.0, 0.0, 0.0, 1.0);
|
2020-03-28 17:06:00 +00:00
|
|
|
const BLACK: Color = Color::Rgba(0.0, 0.0, 0.0, 1.0);
|
2019-08-18 18:07:21 +00:00
|
|
|
//const BG_COLOR: Color = Color::Rgba(1.0, 1.0, 1.0, 0.8);
|
2019-04-26 20:24:05 +00:00
|
|
|
const HP_COLOR: Color = Color::Rgba(0.33, 0.63, 0.0, 1.0);
|
2019-08-18 18:07:21 +00:00
|
|
|
const LOW_HP_COLOR: Color = Color::Rgba(0.93, 0.59, 0.03, 1.0);
|
2019-12-30 12:16:35 +00:00
|
|
|
const CRITICAL_HP_COLOR: Color = Color::Rgba(0.79, 0.19, 0.17, 1.0);
|
2020-01-29 12:01:28 +00:00
|
|
|
const MANA_COLOR: Color = Color::Rgba(0.29, 0.62, 0.75, 0.9);
|
2020-07-31 03:46:08 +00:00
|
|
|
//const TRANSPARENT: Color = Color::Rgba(0.0, 0.0, 0.0, 0.0);
|
2019-08-18 18:07:21 +00:00
|
|
|
//const FOCUS_COLOR: Color = Color::Rgba(1.0, 0.56, 0.04, 1.0);
|
|
|
|
//const RAGE_COLOR: Color = Color::Rgba(0.5, 0.04, 0.13, 1.0);
|
2020-03-16 17:48:10 +00:00
|
|
|
|
|
|
|
// Chat Colors
|
2020-06-12 07:43:20 +00:00
|
|
|
/// Color for chat command errors (yellow !)
|
|
|
|
const ERROR_COLOR: Color = Color::Rgba(1.0, 1.0, 0.0, 1.0);
|
|
|
|
/// Color for chat command info (blue i)
|
|
|
|
const INFO_COLOR: Color = Color::Rgba(0.28, 0.83, 0.71, 1.0);
|
|
|
|
/// Online color
|
|
|
|
const ONLINE_COLOR: Color = Color::Rgba(0.3, 1.0, 0.3, 1.0);
|
|
|
|
/// Offline color
|
|
|
|
const OFFLINE_COLOR: Color = Color::Rgba(1.0, 0.3, 0.3, 1.0);
|
2020-06-02 02:42:26 +00:00
|
|
|
/// Color for a private message from another player
|
2019-07-29 14:40:46 +00:00
|
|
|
const TELL_COLOR: Color = Color::Rgba(0.98, 0.71, 1.0, 1.0);
|
2020-06-02 02:42:26 +00:00
|
|
|
/// Color for local chat
|
2020-06-02 06:11:47 +00:00
|
|
|
const SAY_COLOR: Color = Color::Rgba(1.0, 0.8, 0.8, 1.0);
|
2020-06-02 02:42:26 +00:00
|
|
|
/// Color for group chat
|
2019-07-29 14:40:46 +00:00
|
|
|
const GROUP_COLOR: Color = Color::Rgba(0.47, 0.84, 1.0, 1.0);
|
2020-06-02 02:42:26 +00:00
|
|
|
/// Color for factional chat
|
2019-07-29 14:40:46 +00:00
|
|
|
const FACTION_COLOR: Color = Color::Rgba(0.24, 1.0, 0.48, 1.0);
|
2020-06-02 02:42:26 +00:00
|
|
|
/// Color for regional chat
|
2020-06-12 07:43:20 +00:00
|
|
|
const REGION_COLOR: Color = Color::Rgba(0.8, 1.0, 0.8, 1.0);
|
2020-06-02 02:42:26 +00:00
|
|
|
/// Color for death messages
|
2019-07-29 14:40:46 +00:00
|
|
|
const KILL_COLOR: Color = Color::Rgba(1.0, 0.17, 0.17, 1.0);
|
2020-06-02 02:42:26 +00:00
|
|
|
/// Color for global messages
|
2020-06-12 07:43:20 +00:00
|
|
|
const WORLD_COLOR: Color = Color::Rgba(0.95, 1.0, 0.95, 1.0);
|
2020-07-01 19:05:44 +00:00
|
|
|
/// Color for collected loot messages
|
|
|
|
const LOOT_COLOR: Color = Color::Rgba(0.69, 0.57, 1.0, 1.0);
|
2019-04-26 20:24:05 +00:00
|
|
|
|
2020-07-12 11:10:26 +00:00
|
|
|
//Nametags
|
|
|
|
const GROUP_MEMBER: Color = Color::Rgba(0.47, 0.84, 1.0, 1.0);
|
|
|
|
const DEFAULT_NPC: Color = Color::Rgba(1.0, 1.0, 1.0, 1.0);
|
|
|
|
|
2020-03-16 17:48:10 +00:00
|
|
|
// UI Color-Theme
|
|
|
|
const UI_MAIN: Color = Color::Rgba(0.61, 0.70, 0.70, 1.0); // Greenish Blue
|
|
|
|
//const UI_MAIN: Color = Color::Rgba(0.1, 0.1, 0.1, 0.97); // Dark
|
|
|
|
const UI_HIGHLIGHT_0: Color = Color::Rgba(0.79, 1.09, 1.09, 1.0);
|
|
|
|
//const UI_DARK_0: Color = Color::Rgba(0.25, 0.37, 0.37, 1.0);
|
|
|
|
|
2020-07-12 03:12:03 +00:00
|
|
|
/// Distance at which nametags are visible for group members
|
|
|
|
const NAMETAG_GROUP_RANGE: f32 = 300.0;
|
2020-01-25 03:06:41 +00:00
|
|
|
/// Distance at which nametags are visible
|
|
|
|
const NAMETAG_RANGE: f32 = 40.0;
|
2020-02-01 20:39:39 +00:00
|
|
|
/// Time nametags stay visible after doing damage even if they are out of range
|
|
|
|
/// in seconds
|
2020-01-25 03:06:41 +00:00
|
|
|
const NAMETAG_DMG_TIME: f32 = 60.0;
|
|
|
|
/// Range damaged triggered nametags can be seen
|
|
|
|
const NAMETAG_DMG_RANGE: f32 = 120.0;
|
|
|
|
|
2019-03-15 04:55:52 +00:00
|
|
|
widget_ids! {
|
|
|
|
struct Ids {
|
2019-07-02 19:54:38 +00:00
|
|
|
// Crosshair
|
2019-07-06 23:04:30 +00:00
|
|
|
crosshair_inner,
|
|
|
|
crosshair_outer,
|
2019-07-02 19:54:38 +00:00
|
|
|
|
2020-01-10 00:33:38 +00:00
|
|
|
// SCT
|
|
|
|
player_scts[],
|
|
|
|
player_sct_bgs[],
|
|
|
|
sct_exp_bgs[],
|
|
|
|
sct_exps[],
|
|
|
|
sct_lvl_bg,
|
|
|
|
sct_lvl,
|
|
|
|
hurt_bg,
|
|
|
|
death_bg,
|
|
|
|
sct_bgs[],
|
|
|
|
scts[],
|
|
|
|
|
2020-05-24 06:37:10 +00:00
|
|
|
overheads[],
|
2020-07-29 13:21:12 +00:00
|
|
|
overitems[],
|
2020-05-24 06:37:10 +00:00
|
|
|
|
2019-10-23 19:40:45 +00:00
|
|
|
// Intro Text
|
|
|
|
intro_bg,
|
|
|
|
intro_text,
|
|
|
|
intro_close,
|
|
|
|
intro_close_2,
|
|
|
|
intro_close_3,
|
2019-10-24 18:21:17 +00:00
|
|
|
intro_close_4,
|
|
|
|
intro_close_5,
|
2019-10-23 19:40:45 +00:00
|
|
|
intro_check,
|
|
|
|
intro_check_text,
|
|
|
|
|
2020-06-24 13:44:39 +00:00
|
|
|
// Alpha Disclaimer
|
|
|
|
alpha_text,
|
2019-06-23 19:49:15 +00:00
|
|
|
|
2019-04-26 16:13:30 +00:00
|
|
|
// Debug
|
2019-04-22 18:47:22 +00:00
|
|
|
debug_bg,
|
|
|
|
fps_counter,
|
2019-05-23 08:18:25 +00:00
|
|
|
ping,
|
2019-05-28 18:23:24 +00:00
|
|
|
coordinates,
|
2019-08-06 21:51:13 +00:00
|
|
|
velocity,
|
2020-04-25 00:30:20 +00:00
|
|
|
orientation,
|
2019-06-23 19:49:15 +00:00
|
|
|
loaded_distance,
|
2019-09-01 19:04:03 +00:00
|
|
|
time,
|
2019-11-29 06:04:37 +00:00
|
|
|
entity_count,
|
2019-11-19 15:13:33 +00:00
|
|
|
num_chunks,
|
|
|
|
num_figures,
|
2019-05-07 05:40:03 +00:00
|
|
|
|
2019-04-26 16:13:30 +00:00
|
|
|
// Game Version
|
|
|
|
version,
|
2019-04-02 14:25:14 +00:00
|
|
|
|
2019-04-25 12:20:35 +00:00
|
|
|
// Help
|
2019-03-28 02:25:08 +00:00
|
|
|
help,
|
2019-10-06 19:19:08 +00:00
|
|
|
help_info,
|
2020-01-10 00:33:38 +00:00
|
|
|
debug_info,
|
2019-04-25 12:20:35 +00:00
|
|
|
|
|
|
|
// Window Frames
|
2019-03-15 04:55:52 +00:00
|
|
|
window_frame_0,
|
|
|
|
window_frame_1,
|
|
|
|
window_frame_2,
|
|
|
|
window_frame_3,
|
|
|
|
window_frame_4,
|
|
|
|
window_frame_5,
|
2019-04-25 12:20:35 +00:00
|
|
|
|
2019-03-16 02:03:21 +00:00
|
|
|
button_help2,
|
2019-10-23 19:40:45 +00:00
|
|
|
button_help3,
|
2019-04-30 14:39:19 +00:00
|
|
|
|
|
|
|
// External
|
2019-05-03 16:56:18 +00:00
|
|
|
chat,
|
2019-04-30 14:39:19 +00:00
|
|
|
map,
|
2019-10-16 11:39:41 +00:00
|
|
|
world_map,
|
2019-04-30 14:39:19 +00:00
|
|
|
character_window,
|
2020-05-14 16:56:10 +00:00
|
|
|
popup,
|
2019-05-07 17:21:53 +00:00
|
|
|
minimap,
|
2019-05-04 10:43:37 +00:00
|
|
|
bag,
|
2019-08-07 13:14:26 +00:00
|
|
|
social,
|
|
|
|
quest,
|
|
|
|
spell,
|
2019-05-04 06:07:23 +00:00
|
|
|
skillbar,
|
2019-05-04 10:43:37 +00:00
|
|
|
buttons,
|
2019-05-03 16:56:18 +00:00
|
|
|
esc_menu,
|
|
|
|
small_window,
|
2019-08-07 13:14:26 +00:00
|
|
|
social_window,
|
2020-07-14 20:11:39 +00:00
|
|
|
crafting_window,
|
2019-05-03 16:56:18 +00:00
|
|
|
settings_window,
|
2020-07-12 00:39:50 +00:00
|
|
|
group_window,
|
2020-03-26 21:22:21 +00:00
|
|
|
|
|
|
|
// Free look indicator
|
|
|
|
free_look_txt,
|
|
|
|
free_look_bg,
|
2020-06-03 17:59:09 +00:00
|
|
|
|
2020-06-06 18:09:01 +00:00
|
|
|
// Auto walk indicator
|
|
|
|
auto_walk_txt,
|
|
|
|
auto_walk_bg,
|
|
|
|
|
2020-06-03 17:59:09 +00:00
|
|
|
// Example Quest
|
|
|
|
quest_bg,
|
|
|
|
q_headline_bg,
|
|
|
|
q_headline,
|
|
|
|
q_text_bg,
|
|
|
|
q_text,
|
|
|
|
accept_button,
|
2019-03-15 04:55:52 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-05-23 09:30:00 +00:00
|
|
|
pub struct DebugInfo {
|
|
|
|
pub tps: f64,
|
|
|
|
pub ping_ms: f64,
|
2019-06-14 15:27:05 +00:00
|
|
|
pub coordinates: Option<comp::Pos>,
|
2019-08-06 21:51:13 +00:00
|
|
|
pub velocity: Option<comp::Vel>,
|
2020-04-25 00:30:20 +00:00
|
|
|
pub ori: Option<comp::Ori>,
|
2019-11-19 15:13:33 +00:00
|
|
|
pub num_chunks: u32,
|
|
|
|
pub num_visible_chunks: u32,
|
|
|
|
pub num_figures: u32,
|
|
|
|
pub num_figures_visible: u32,
|
2019-05-23 09:30:00 +00:00
|
|
|
}
|
2019-07-27 19:26:31 +00:00
|
|
|
|
2020-05-18 22:40:28 +00:00
|
|
|
pub struct HudInfo {
|
|
|
|
pub is_aiming: bool,
|
|
|
|
pub is_first_person: bool,
|
2020-04-24 08:02:47 +00:00
|
|
|
pub target_entity: Option<specs::Entity>,
|
2020-07-12 00:39:50 +00:00
|
|
|
pub selected_entity: Option<(specs::Entity, std::time::Instant)>,
|
2020-05-18 22:40:28 +00:00
|
|
|
}
|
|
|
|
|
2019-03-16 02:03:21 +00:00
|
|
|
pub enum Event {
|
2020-07-23 12:10:13 +00:00
|
|
|
ToggleTips(bool),
|
2019-03-16 02:03:21 +00:00
|
|
|
SendMessage(String),
|
2019-06-05 15:57:48 +00:00
|
|
|
AdjustMousePan(u32),
|
|
|
|
AdjustMouseZoom(u32),
|
2019-10-02 13:09:05 +00:00
|
|
|
ToggleZoomInvert(bool),
|
2019-12-06 22:49:17 +00:00
|
|
|
ToggleMouseYInvert(bool),
|
2020-04-23 22:59:34 +00:00
|
|
|
ToggleSmoothPan(bool),
|
2019-05-19 00:45:02 +00:00
|
|
|
AdjustViewDistance(u32),
|
2020-04-25 13:04:30 +00:00
|
|
|
AdjustSpriteRenderDistance(u32),
|
2020-04-26 01:44:56 +00:00
|
|
|
AdjustFigureLoDRenderDistance(u32),
|
2019-09-24 16:18:09 +00:00
|
|
|
AdjustMusicVolume(f32),
|
2019-09-24 16:25:24 +00:00
|
|
|
AdjustSfxVolume(f32),
|
2019-05-20 14:53:12 +00:00
|
|
|
ChangeAudioDevice(String),
|
2019-06-06 19:11:39 +00:00
|
|
|
ChangeMaxFPS(u32),
|
2019-08-05 16:37:52 +00:00
|
|
|
ChangeFOV(u16),
|
2020-02-12 13:55:26 +00:00
|
|
|
ChangeGamma(f32),
|
2020-07-01 19:05:44 +00:00
|
|
|
MapZoom(f64),
|
2020-01-02 03:48:11 +00:00
|
|
|
AdjustWindowSize([u16; 2]),
|
|
|
|
ToggleFullscreen,
|
2019-09-26 07:28:40 +00:00
|
|
|
ChangeAaMode(AaMode),
|
2020-01-19 03:58:25 +00:00
|
|
|
ChangeCloudMode(CloudMode),
|
|
|
|
ChangeFluidMode(FluidMode),
|
2019-07-07 00:15:22 +00:00
|
|
|
CrosshairTransp(f32),
|
2019-10-23 19:40:45 +00:00
|
|
|
ChatTransp(f32),
|
2020-06-24 05:46:29 +00:00
|
|
|
ChatCharName(bool),
|
2019-07-23 01:02:57 +00:00
|
|
|
CrosshairType(CrosshairType),
|
2019-08-18 18:07:21 +00:00
|
|
|
ToggleXpBar(XpBar),
|
2019-10-23 19:40:45 +00:00
|
|
|
Intro(Intro),
|
2019-08-18 18:07:21 +00:00
|
|
|
ToggleBarNumbers(BarNumbers),
|
|
|
|
ToggleShortcutNumbers(ShortcutNumbers),
|
2020-01-10 00:33:38 +00:00
|
|
|
Sct(bool),
|
|
|
|
SctPlayerBatch(bool),
|
|
|
|
SctDamageBatch(bool),
|
2020-05-25 01:29:47 +00:00
|
|
|
SpeechBubbleDarkMode(bool),
|
2020-06-14 03:13:01 +00:00
|
|
|
SpeechBubbleIcon(bool),
|
2020-01-10 00:33:38 +00:00
|
|
|
ToggleDebug(bool),
|
2019-07-26 02:28:53 +00:00
|
|
|
UiScale(ScaleChange),
|
2019-06-02 02:17:36 +00:00
|
|
|
CharacterSelection,
|
2020-04-10 02:36:35 +00:00
|
|
|
UseSlot(comp::slot::Slot),
|
|
|
|
SwapSlots(comp::slot::Slot, comp::slot::Slot),
|
|
|
|
DropSlot(comp::slot::Slot),
|
2020-06-16 13:55:37 +00:00
|
|
|
ChangeHotbarState(HotbarState),
|
2020-04-11 06:33:06 +00:00
|
|
|
Ability3(bool),
|
2019-03-16 02:03:21 +00:00
|
|
|
Logout,
|
|
|
|
Quit,
|
2020-01-17 23:43:18 +00:00
|
|
|
ChangeLanguage(LanguageMetadata),
|
2020-04-08 17:36:37 +00:00
|
|
|
ChangeBinding(GameInput),
|
2020-07-12 18:59:18 +00:00
|
|
|
ResetBindings,
|
2020-03-27 18:35:52 +00:00
|
|
|
ChangeFreeLookBehavior(PressBehavior),
|
2020-06-06 18:09:01 +00:00
|
|
|
ChangeAutoWalkBehavior(PressBehavior),
|
|
|
|
ChangeStopAutoWalkOnInput(bool),
|
2020-07-14 20:11:39 +00:00
|
|
|
CraftRecipe(String),
|
2020-07-12 00:39:50 +00:00
|
|
|
InviteMember(common::sync::Uid),
|
|
|
|
AcceptInvite,
|
2020-07-19 21:49:18 +00:00
|
|
|
DeclineInvite,
|
2020-07-12 00:39:50 +00:00
|
|
|
KickMember(common::sync::Uid),
|
|
|
|
LeaveGroup,
|
|
|
|
AssignLeader(common::sync::Uid),
|
2019-03-16 02:03:21 +00:00
|
|
|
}
|
|
|
|
|
2019-05-17 09:22:32 +00:00
|
|
|
// TODO: Are these the possible layouts we want?
|
|
|
|
// TODO: Maybe replace this with bitflags.
|
2020-02-01 20:39:39 +00:00
|
|
|
// `map` is not here because it currently is displayed over the top of other
|
|
|
|
// open windows.
|
2019-05-04 10:43:37 +00:00
|
|
|
#[derive(PartialEq)]
|
|
|
|
pub enum Windows {
|
2019-08-07 13:14:26 +00:00
|
|
|
Settings, // Display settings window.
|
2019-03-28 04:00:51 +00:00
|
|
|
None,
|
|
|
|
}
|
|
|
|
|
2019-07-23 01:02:57 +00:00
|
|
|
#[derive(Clone, Copy, Debug, Serialize, Deserialize)]
|
|
|
|
pub enum CrosshairType {
|
|
|
|
Round,
|
|
|
|
RoundEdges,
|
|
|
|
Edges,
|
|
|
|
}
|
2019-08-18 18:07:21 +00:00
|
|
|
#[derive(Clone, Copy, Debug, Serialize, Deserialize)]
|
2019-10-23 19:40:45 +00:00
|
|
|
pub enum Intro {
|
|
|
|
Show,
|
|
|
|
Never,
|
|
|
|
}
|
|
|
|
#[derive(Clone, Copy, Debug, Serialize, Deserialize)]
|
2019-08-18 18:07:21 +00:00
|
|
|
pub enum XpBar {
|
|
|
|
Always,
|
|
|
|
OnGain,
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Clone, Copy, Debug, Serialize, Deserialize)]
|
|
|
|
pub enum BarNumbers {
|
|
|
|
Values,
|
|
|
|
Percent,
|
|
|
|
Off,
|
|
|
|
}
|
|
|
|
#[derive(Clone, Copy, Debug, Serialize, Deserialize)]
|
|
|
|
pub enum ShortcutNumbers {
|
|
|
|
On,
|
|
|
|
Off,
|
|
|
|
}
|
2020-03-27 18:35:52 +00:00
|
|
|
#[derive(Clone, Copy, Debug, Serialize, Deserialize)]
|
|
|
|
pub enum PressBehavior {
|
|
|
|
Toggle = 0,
|
|
|
|
Hold = 1,
|
|
|
|
}
|
2019-07-23 01:02:57 +00:00
|
|
|
|
2019-05-04 17:24:26 +00:00
|
|
|
pub struct Show {
|
|
|
|
ui: bool,
|
2019-10-23 19:40:45 +00:00
|
|
|
intro: bool,
|
2019-05-04 17:24:26 +00:00
|
|
|
help: bool,
|
2020-07-14 20:11:39 +00:00
|
|
|
crafting: bool,
|
2019-05-04 17:24:26 +00:00
|
|
|
debug: bool,
|
|
|
|
bag: bool,
|
2019-08-07 13:14:26 +00:00
|
|
|
social: bool,
|
|
|
|
spell: bool,
|
2020-07-12 00:39:50 +00:00
|
|
|
group: bool,
|
2020-07-25 23:21:15 +00:00
|
|
|
group_menu: bool,
|
2019-05-04 17:24:26 +00:00
|
|
|
esc_menu: bool,
|
|
|
|
open_windows: Windows,
|
|
|
|
map: bool,
|
2019-05-07 05:40:03 +00:00
|
|
|
mini_map: bool,
|
2019-05-21 04:55:20 +00:00
|
|
|
ingame: bool,
|
2019-06-02 02:17:36 +00:00
|
|
|
settings_tab: SettingsTab,
|
2019-08-07 13:14:26 +00:00
|
|
|
social_tab: SocialTab,
|
2019-05-09 16:55:13 +00:00
|
|
|
want_grab: bool,
|
2020-03-16 17:48:10 +00:00
|
|
|
stats: bool,
|
2020-03-26 21:22:21 +00:00
|
|
|
free_look: bool,
|
2020-06-06 18:09:01 +00:00
|
|
|
auto_walk: bool,
|
2019-05-04 17:24:26 +00:00
|
|
|
}
|
|
|
|
impl Show {
|
2019-05-25 12:59:25 +00:00
|
|
|
fn bag(&mut self, open: bool) {
|
2020-07-14 20:11:39 +00:00
|
|
|
if !self.esc_menu {
|
|
|
|
self.bag = open;
|
|
|
|
self.map = false;
|
|
|
|
self.want_grab = !open;
|
|
|
|
}
|
2019-05-25 12:59:25 +00:00
|
|
|
}
|
2020-02-01 20:39:39 +00:00
|
|
|
|
|
|
|
fn toggle_bag(&mut self) { self.bag(!self.bag); }
|
|
|
|
|
2019-05-25 12:59:25 +00:00
|
|
|
fn map(&mut self, open: bool) {
|
2020-07-14 20:11:39 +00:00
|
|
|
if !self.esc_menu {
|
|
|
|
self.map = open;
|
|
|
|
self.bag = false;
|
|
|
|
self.crafting = false;
|
|
|
|
self.social = false;
|
|
|
|
self.spell = false;
|
|
|
|
self.want_grab = !open;
|
|
|
|
}
|
2019-05-25 12:59:25 +00:00
|
|
|
}
|
2020-02-01 20:39:39 +00:00
|
|
|
|
2019-08-07 13:14:26 +00:00
|
|
|
fn social(&mut self, open: bool) {
|
2020-07-14 20:11:39 +00:00
|
|
|
if !self.esc_menu {
|
|
|
|
self.social = open;
|
|
|
|
self.spell = false;
|
|
|
|
self.want_grab = !open;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
fn crafting(&mut self, open: bool) {
|
|
|
|
if !self.esc_menu {
|
|
|
|
self.crafting = open;
|
|
|
|
self.bag = open;
|
|
|
|
self.want_grab = !open;
|
|
|
|
}
|
2019-08-07 13:14:26 +00:00
|
|
|
}
|
2020-02-01 20:39:39 +00:00
|
|
|
|
2019-08-07 13:14:26 +00:00
|
|
|
fn spell(&mut self, open: bool) {
|
2020-07-14 20:11:39 +00:00
|
|
|
if !self.esc_menu {
|
|
|
|
self.social = false;
|
|
|
|
self.crafting = false;
|
|
|
|
self.spell = open;
|
|
|
|
self.want_grab = !open;
|
|
|
|
}
|
2019-08-07 13:14:26 +00:00
|
|
|
}
|
2019-05-07 17:21:53 +00:00
|
|
|
|
2020-02-01 20:39:39 +00:00
|
|
|
fn toggle_map(&mut self) { self.map(!self.map) }
|
2019-05-07 17:21:53 +00:00
|
|
|
|
2020-02-01 20:39:39 +00:00
|
|
|
fn toggle_mini_map(&mut self) { self.mini_map = !self.mini_map; }
|
|
|
|
|
2019-05-25 12:59:25 +00:00
|
|
|
fn settings(&mut self, open: bool) {
|
2020-07-14 20:11:39 +00:00
|
|
|
if !self.esc_menu {
|
|
|
|
self.open_windows = if open {
|
|
|
|
Windows::Settings
|
|
|
|
} else {
|
|
|
|
Windows::None
|
|
|
|
};
|
|
|
|
self.bag = false;
|
|
|
|
self.social = false;
|
|
|
|
self.crafting = false;
|
|
|
|
self.spell = false;
|
|
|
|
self.want_grab = !open;
|
|
|
|
}
|
2019-05-25 12:59:25 +00:00
|
|
|
}
|
2020-02-01 20:39:39 +00:00
|
|
|
|
2019-05-25 12:59:25 +00:00
|
|
|
fn toggle_settings(&mut self) {
|
|
|
|
match self.open_windows {
|
|
|
|
Windows::Settings => self.settings(false),
|
|
|
|
_ => self.settings(true),
|
|
|
|
};
|
2019-05-04 17:24:26 +00:00
|
|
|
}
|
2019-05-07 17:21:53 +00:00
|
|
|
|
2020-02-01 20:39:39 +00:00
|
|
|
fn toggle_help(&mut self) { self.help = !self.help }
|
2019-05-07 17:21:53 +00:00
|
|
|
|
2020-02-01 20:39:39 +00:00
|
|
|
fn toggle_ui(&mut self) { self.ui = !self.ui; }
|
2019-05-04 17:24:26 +00:00
|
|
|
|
2020-03-01 22:18:22 +00:00
|
|
|
fn toggle_windows(&mut self, global_state: &mut GlobalState) {
|
2019-05-04 17:24:26 +00:00
|
|
|
if self.bag
|
|
|
|
|| self.esc_menu
|
|
|
|
|| self.map
|
2019-08-07 13:14:26 +00:00
|
|
|
|| self.social
|
2020-07-14 20:11:39 +00:00
|
|
|
|| self.crafting
|
2019-08-07 13:14:26 +00:00
|
|
|
|| self.spell
|
2020-04-04 21:51:06 +00:00
|
|
|
|| self.help
|
|
|
|
|| self.intro
|
2019-05-04 17:24:26 +00:00
|
|
|
|| match self.open_windows {
|
|
|
|
Windows::None => false,
|
|
|
|
_ => true,
|
|
|
|
}
|
|
|
|
{
|
|
|
|
self.bag = false;
|
|
|
|
self.esc_menu = false;
|
2020-04-04 21:51:06 +00:00
|
|
|
self.help = false;
|
|
|
|
self.intro = false;
|
2019-05-04 17:24:26 +00:00
|
|
|
self.map = false;
|
2019-08-07 13:14:26 +00:00
|
|
|
self.social = false;
|
|
|
|
self.spell = false;
|
2020-07-14 20:11:39 +00:00
|
|
|
self.crafting = false;
|
2019-05-04 17:24:26 +00:00
|
|
|
self.open_windows = Windows::None;
|
2019-05-09 16:55:13 +00:00
|
|
|
self.want_grab = true;
|
2020-03-01 22:18:22 +00:00
|
|
|
|
|
|
|
// Unpause the game if we are on singleplayer
|
2020-07-15 23:19:11 +00:00
|
|
|
#[cfg(feature = "singleplayer")]
|
2020-03-07 22:16:00 +00:00
|
|
|
global_state.unpause();
|
2019-05-04 17:24:26 +00:00
|
|
|
} else {
|
|
|
|
self.esc_menu = true;
|
2019-05-09 16:55:13 +00:00
|
|
|
self.want_grab = false;
|
2020-03-01 22:18:22 +00:00
|
|
|
|
2020-07-15 23:19:11 +00:00
|
|
|
// Pause the game if we are on singleplayer
|
2020-03-07 22:16:00 +00:00
|
|
|
#[cfg(feature = "singleplayer")]
|
2020-07-15 23:19:11 +00:00
|
|
|
global_state.pause();
|
2019-05-04 17:24:26 +00:00
|
|
|
}
|
|
|
|
}
|
2019-06-02 02:17:36 +00:00
|
|
|
|
|
|
|
fn open_setting_tab(&mut self, tab: SettingsTab) {
|
|
|
|
self.open_windows = Windows::Settings;
|
|
|
|
self.esc_menu = false;
|
|
|
|
self.settings_tab = tab;
|
|
|
|
self.bag = false;
|
|
|
|
self.want_grab = false;
|
|
|
|
}
|
2019-08-07 13:14:26 +00:00
|
|
|
|
|
|
|
fn toggle_social(&mut self) {
|
2020-08-02 23:53:02 +00:00
|
|
|
self.social(!self.social);
|
2019-08-07 13:14:26 +00:00
|
|
|
self.spell = false;
|
|
|
|
}
|
|
|
|
|
2020-07-14 20:11:39 +00:00
|
|
|
fn toggle_crafting(&mut self) { self.crafting(!self.crafting) }
|
|
|
|
|
2019-08-07 13:14:26 +00:00
|
|
|
fn open_social_tab(&mut self, social_tab: SocialTab) {
|
|
|
|
self.social_tab = social_tab;
|
|
|
|
self.spell = false;
|
|
|
|
}
|
|
|
|
|
|
|
|
fn toggle_spell(&mut self) {
|
|
|
|
self.spell = !self.spell;
|
|
|
|
self.social = false;
|
|
|
|
}
|
2019-05-04 17:24:26 +00:00
|
|
|
}
|
|
|
|
|
2019-09-25 20:18:40 +00:00
|
|
|
pub struct Hud {
|
2019-03-15 04:55:52 +00:00
|
|
|
ui: Ui,
|
|
|
|
ids: Ids,
|
2020-02-06 17:34:32 +00:00
|
|
|
world_map: (/* Id */ Rotations, Vec2<u32>),
|
2019-03-15 04:55:52 +00:00
|
|
|
imgs: Imgs,
|
2019-10-09 19:28:05 +00:00
|
|
|
item_imgs: ItemImgs,
|
2020-01-26 19:29:46 +00:00
|
|
|
fonts: ConrodVoxygenFonts,
|
2019-09-25 16:51:47 +00:00
|
|
|
rot_imgs: ImgsRot,
|
2020-06-02 02:42:26 +00:00
|
|
|
new_messages: VecDeque<comp::ChatMsg>,
|
|
|
|
new_notifications: VecDeque<common::msg::Notification>,
|
2020-06-04 07:11:35 +00:00
|
|
|
speech_bubbles: HashMap<Uid, comp::SpeechBubble>,
|
2019-05-04 17:24:26 +00:00
|
|
|
show: Show,
|
2020-06-03 17:59:09 +00:00
|
|
|
//never_show: bool,
|
|
|
|
//intro: bool,
|
|
|
|
//intro_2: bool,
|
2019-05-07 03:25:25 +00:00
|
|
|
to_focus: Option<Option<widget::Id>>,
|
2019-07-26 21:05:39 +00:00
|
|
|
force_ungrab: bool,
|
2019-07-05 16:21:11 +00:00
|
|
|
force_chat_input: Option<String>,
|
|
|
|
force_chat_cursor: Option<Index>,
|
2020-05-08 21:38:58 +00:00
|
|
|
tab_complete: Option<String>,
|
2019-12-30 12:16:35 +00:00
|
|
|
pulse: f32,
|
2020-01-10 00:33:38 +00:00
|
|
|
velocity: f32,
|
2020-01-26 19:29:46 +00:00
|
|
|
voxygen_i18n: std::sync::Arc<VoxygenLocalization>,
|
2020-04-06 15:25:45 +00:00
|
|
|
slot_manager: slots::SlotManager,
|
2020-04-11 06:33:06 +00:00
|
|
|
hotbar: hotbar::State,
|
|
|
|
events: Vec<Event>,
|
2020-05-18 22:40:28 +00:00
|
|
|
crosshair_opacity: f32,
|
2019-03-15 04:55:52 +00:00
|
|
|
}
|
|
|
|
|
2019-09-25 20:18:40 +00:00
|
|
|
impl Hud {
|
2019-10-16 11:39:41 +00:00
|
|
|
pub fn new(global_state: &mut GlobalState, client: &Client) -> Self {
|
2019-07-26 02:28:53 +00:00
|
|
|
let window = &mut global_state.window;
|
|
|
|
let settings = &global_state.settings;
|
|
|
|
|
2019-03-15 04:55:52 +00:00
|
|
|
let mut ui = Ui::new(window).unwrap();
|
2019-07-26 02:28:53 +00:00
|
|
|
ui.set_scaling_mode(settings.gameplay.ui_scale);
|
2019-05-17 09:22:32 +00:00
|
|
|
// Generate ids.
|
2019-03-16 02:03:21 +00:00
|
|
|
let ids = Ids::new(ui.id_generator());
|
2019-10-16 11:39:41 +00:00
|
|
|
// Load world map
|
2020-01-11 20:38:30 +00:00
|
|
|
let world_map = (
|
2020-02-06 17:34:32 +00:00
|
|
|
ui.add_graphic_with_rotations(Graphic::Image(client.world_map.0.clone())),
|
2020-01-11 20:38:30 +00:00
|
|
|
client.world_map.1,
|
|
|
|
);
|
2019-05-17 09:22:32 +00:00
|
|
|
// Load images.
|
|
|
|
let imgs = Imgs::load(&mut ui).expect("Failed to load images!");
|
2019-09-25 20:18:40 +00:00
|
|
|
// Load rotation images.
|
|
|
|
let rot_imgs = ImgsRot::load(&mut ui).expect("Failed to load rot images!");
|
2019-10-09 19:28:05 +00:00
|
|
|
// Load item images.
|
2020-04-04 05:40:00 +00:00
|
|
|
let item_imgs = ItemImgs::new(&mut ui, imgs.not_found);
|
2020-06-16 13:55:37 +00:00
|
|
|
// Load language.
|
2020-01-26 19:29:46 +00:00
|
|
|
let voxygen_i18n = load_expect::<VoxygenLocalization>(&i18n_asset_key(
|
|
|
|
&global_state.settings.language.selected_language,
|
|
|
|
));
|
2019-05-17 09:22:32 +00:00
|
|
|
// Load fonts.
|
2020-01-26 19:29:46 +00:00
|
|
|
let fonts = ConrodVoxygenFonts::load(&voxygen_i18n.fonts, &mut ui)
|
|
|
|
.expect("Impossible to load fonts!");
|
2020-06-16 13:55:37 +00:00
|
|
|
// Get the server name.
|
|
|
|
let server = &client.server_info.name;
|
|
|
|
// Get the id, unwrap is safe because this CANNOT be None at this
|
|
|
|
// point.
|
|
|
|
let character_id = client.active_character_id.unwrap();
|
|
|
|
// Create a new HotbarState from the persisted slots.
|
|
|
|
let hotbar_state =
|
|
|
|
HotbarState::new(global_state.profile.get_hotbar_slots(server, character_id));
|
2019-04-20 22:02:48 +00:00
|
|
|
|
2020-04-06 15:25:45 +00:00
|
|
|
let slot_manager = slots::SlotManager::new(ui.id_generator(), Vec2::broadcast(40.0));
|
2020-04-06 06:15:22 +00:00
|
|
|
|
2019-03-15 04:55:52 +00:00
|
|
|
Self {
|
|
|
|
ui,
|
|
|
|
imgs,
|
2019-10-16 11:39:41 +00:00
|
|
|
world_map,
|
2019-09-25 16:51:47 +00:00
|
|
|
rot_imgs,
|
2019-10-09 19:28:05 +00:00
|
|
|
item_imgs,
|
2019-04-30 20:43:55 +00:00
|
|
|
fonts,
|
2019-07-26 21:05:39 +00:00
|
|
|
ids,
|
2019-05-03 16:56:18 +00:00
|
|
|
new_messages: VecDeque::new(),
|
2020-06-04 07:11:35 +00:00
|
|
|
new_notifications: VecDeque::new(),
|
|
|
|
speech_bubbles: HashMap::new(),
|
2020-06-03 17:59:09 +00:00
|
|
|
//intro: false,
|
|
|
|
//intro_2: false,
|
2019-05-04 17:24:26 +00:00
|
|
|
show: Show {
|
2019-05-18 19:03:13 +00:00
|
|
|
help: false,
|
2019-10-23 19:40:45 +00:00
|
|
|
intro: true,
|
2020-01-10 00:33:38 +00:00
|
|
|
debug: false,
|
2019-05-04 17:24:26 +00:00
|
|
|
bag: false,
|
|
|
|
esc_menu: false,
|
|
|
|
open_windows: Windows::None,
|
|
|
|
map: false,
|
2020-07-14 20:11:39 +00:00
|
|
|
crafting: false,
|
2019-05-04 17:24:26 +00:00
|
|
|
ui: true,
|
2019-08-07 13:14:26 +00:00
|
|
|
social: false,
|
|
|
|
spell: false,
|
2020-07-12 00:39:50 +00:00
|
|
|
group: false,
|
2020-07-25 23:21:15 +00:00
|
|
|
group_menu: false,
|
2020-02-06 17:34:32 +00:00
|
|
|
mini_map: true,
|
2019-06-02 02:17:36 +00:00
|
|
|
settings_tab: SettingsTab::Interface,
|
2019-08-07 13:14:26 +00:00
|
|
|
social_tab: SocialTab::Online,
|
2019-05-09 16:55:13 +00:00
|
|
|
want_grab: true,
|
2019-05-21 04:55:20 +00:00
|
|
|
ingame: true,
|
2020-03-16 17:48:10 +00:00
|
|
|
stats: false,
|
2020-03-26 21:22:21 +00:00
|
|
|
free_look: false,
|
2020-06-06 18:09:01 +00:00
|
|
|
auto_walk: false,
|
2019-05-06 12:28:57 +00:00
|
|
|
},
|
|
|
|
to_focus: None,
|
2020-06-03 17:59:09 +00:00
|
|
|
//never_show: false,
|
2019-05-09 08:55:32 +00:00
|
|
|
force_ungrab: false,
|
2019-07-05 16:21:11 +00:00
|
|
|
force_chat_input: None,
|
|
|
|
force_chat_cursor: None,
|
2020-05-08 21:38:58 +00:00
|
|
|
tab_complete: None,
|
2019-12-30 12:16:35 +00:00
|
|
|
pulse: 0.0,
|
2020-01-10 00:33:38 +00:00
|
|
|
velocity: 0.0,
|
2020-01-26 19:29:46 +00:00
|
|
|
voxygen_i18n,
|
2020-04-06 06:15:22 +00:00
|
|
|
slot_manager,
|
2020-06-16 13:55:37 +00:00
|
|
|
hotbar: hotbar_state,
|
2020-04-11 06:33:06 +00:00
|
|
|
events: Vec::new(),
|
2020-05-18 22:40:28 +00:00
|
|
|
crosshair_opacity: 0.0,
|
2019-03-15 04:55:52 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-01-26 19:29:46 +00:00
|
|
|
pub fn update_language(&mut self, voxygen_i18n: std::sync::Arc<VoxygenLocalization>) {
|
|
|
|
self.voxygen_i18n = voxygen_i18n;
|
|
|
|
self.fonts = ConrodVoxygenFonts::load(&self.voxygen_i18n.fonts, &mut self.ui)
|
|
|
|
.expect("Impossible to load fonts!");
|
|
|
|
}
|
|
|
|
|
2020-06-10 19:47:36 +00:00
|
|
|
#[allow(clippy::assign_op_pattern)] // TODO: Pending review in #587
|
|
|
|
#[allow(clippy::single_match)] // TODO: Pending review in #587
|
2019-05-24 12:43:03 +00:00
|
|
|
fn update_layout(
|
|
|
|
&mut self,
|
|
|
|
client: &Client,
|
|
|
|
global_state: &GlobalState,
|
|
|
|
debug_info: DebugInfo,
|
2019-12-30 12:16:35 +00:00
|
|
|
dt: Duration,
|
2020-05-18 22:40:28 +00:00
|
|
|
info: HudInfo,
|
2020-07-10 14:00:20 +00:00
|
|
|
camera: &Camera,
|
2019-05-24 12:43:03 +00:00
|
|
|
) -> Vec<Event> {
|
2020-04-11 06:33:06 +00:00
|
|
|
let mut events = std::mem::replace(&mut self.events, Vec::new());
|
2019-09-25 16:51:47 +00:00
|
|
|
let (ref mut ui_widgets, ref mut tooltip_manager) = self.ui.set_widgets();
|
2019-12-30 12:16:35 +00:00
|
|
|
// pulse time for pulsating elements
|
|
|
|
self.pulse = self.pulse + dt.as_secs_f32();
|
2020-01-10 00:33:38 +00:00
|
|
|
self.velocity = match debug_info.velocity {
|
|
|
|
Some(velocity) => velocity.0.magnitude(),
|
|
|
|
None => 0.0,
|
|
|
|
};
|
2019-06-28 12:08:12 +00:00
|
|
|
|
2019-10-18 10:03:01 +00:00
|
|
|
let version = format!(
|
|
|
|
"{}-{}",
|
|
|
|
env!("CARGO_PKG_VERSION"),
|
|
|
|
common::util::GIT_VERSION.to_string()
|
|
|
|
);
|
2019-07-02 19:54:38 +00:00
|
|
|
|
2020-01-10 00:33:38 +00:00
|
|
|
if self.show.ingame {
|
2019-08-07 13:14:26 +00:00
|
|
|
let ecs = client.state().ecs();
|
|
|
|
let pos = ecs.read_storage::<comp::Pos>();
|
|
|
|
let stats = ecs.read_storage::<comp::Stats>();
|
2020-01-12 16:43:25 +00:00
|
|
|
let energy = ecs.read_storage::<comp::Energy>();
|
2020-01-10 00:33:38 +00:00
|
|
|
let hp_floater_lists = ecs.read_storage::<vcomp::HpFloaterList>();
|
2020-06-04 07:11:35 +00:00
|
|
|
let uids = ecs.read_storage::<common::sync::Uid>();
|
2020-01-10 00:33:38 +00:00
|
|
|
let interpolated = ecs.read_storage::<vcomp::Interpolated>();
|
2019-08-07 13:14:26 +00:00
|
|
|
let players = ecs.read_storage::<comp::Player>();
|
|
|
|
let scales = ecs.read_storage::<comp::Scale>();
|
2020-02-05 01:30:31 +00:00
|
|
|
let bodies = ecs.read_storage::<comp::Body>();
|
2020-07-29 13:21:12 +00:00
|
|
|
let items = ecs.read_storage::<comp::Item>();
|
2019-08-07 13:14:26 +00:00
|
|
|
let entities = ecs.entities();
|
|
|
|
let me = client.entity();
|
2019-12-30 12:16:35 +00:00
|
|
|
let own_level = stats
|
|
|
|
.get(client.entity())
|
|
|
|
.map_or(0, |stats| stats.level.level());
|
2020-01-18 01:10:12 +00:00
|
|
|
//self.input = client.read_storage::<comp::ControllerInputs>();
|
2020-01-10 00:33:38 +00:00
|
|
|
if let Some(stats) = stats.get(me) {
|
|
|
|
// Hurt Frame
|
|
|
|
let hp_percentage =
|
|
|
|
stats.health.current() as f32 / stats.health.maximum() as f32 * 100.0;
|
|
|
|
if hp_percentage < 10.0 && !stats.is_dead {
|
|
|
|
let hurt_fade =
|
2020-02-01 20:39:39 +00:00
|
|
|
(self.pulse * (10.0 - hp_percentage as f32) * 0.1/* speed factor */).sin()
|
2020-01-10 00:33:38 +00:00
|
|
|
* 0.5
|
|
|
|
+ 0.6; //Animation timer
|
|
|
|
Image::new(self.imgs.hurt_bg)
|
|
|
|
.wh_of(ui_widgets.window)
|
|
|
|
.middle_of(ui_widgets.window)
|
|
|
|
.graphics_for(ui_widgets.window)
|
|
|
|
.color(Some(Color::Rgba(1.0, 1.0, 1.0, hurt_fade)))
|
|
|
|
.set(self.ids.hurt_bg, ui_widgets);
|
|
|
|
}
|
2020-06-24 13:44:39 +00:00
|
|
|
// Alpha Disclaimer
|
|
|
|
Text::new(&format!("Veloren Pre-Alpha {}", env!("CARGO_PKG_VERSION")))
|
|
|
|
.font_id(self.fonts.cyri.conrod_id)
|
|
|
|
.font_size(self.fonts.cyri.scale(10))
|
|
|
|
.color(TEXT_COLOR)
|
|
|
|
.mid_top_with_margin_on(ui_widgets.window, 2.0)
|
|
|
|
.set(self.ids.alpha_text, ui_widgets);
|
|
|
|
|
2020-01-10 00:33:38 +00:00
|
|
|
// Death Frame
|
|
|
|
if stats.is_dead {
|
|
|
|
Image::new(self.imgs.death_bg)
|
|
|
|
.wh_of(ui_widgets.window)
|
|
|
|
.middle_of(ui_widgets.window)
|
|
|
|
.graphics_for(ui_widgets.window)
|
|
|
|
.color(Some(Color::Rgba(0.0, 0.0, 0.0, 1.0)))
|
|
|
|
.set(self.ids.death_bg, ui_widgets);
|
|
|
|
}
|
|
|
|
// Crosshair
|
2020-05-18 22:40:28 +00:00
|
|
|
let show_crosshair = (info.is_aiming || info.is_first_person) && !stats.is_dead;
|
2020-05-18 23:35:58 +00:00
|
|
|
self.crosshair_opacity = Lerp::lerp(
|
|
|
|
self.crosshair_opacity,
|
|
|
|
if show_crosshair { 1.0 } else { 0.0 },
|
|
|
|
5.0 * dt.as_secs_f32(),
|
|
|
|
);
|
2020-05-18 22:40:28 +00:00
|
|
|
|
|
|
|
if !self.show.help {
|
2020-01-10 00:33:38 +00:00
|
|
|
Image::new(
|
|
|
|
// TODO: Do we want to match on this every frame?
|
|
|
|
match global_state.settings.gameplay.crosshair_type {
|
|
|
|
CrosshairType::Round => self.imgs.crosshair_outer_round,
|
|
|
|
CrosshairType::RoundEdges => self.imgs.crosshair_outer_round_edges,
|
|
|
|
CrosshairType::Edges => self.imgs.crosshair_outer_edges,
|
|
|
|
},
|
|
|
|
)
|
|
|
|
.w_h(21.0 * 1.5, 21.0 * 1.5)
|
|
|
|
.middle_of(ui_widgets.window)
|
|
|
|
.color(Some(Color::Rgba(
|
|
|
|
1.0,
|
|
|
|
1.0,
|
|
|
|
1.0,
|
2020-05-18 22:40:28 +00:00
|
|
|
self.crosshair_opacity * global_state.settings.gameplay.crosshair_transp,
|
2020-01-10 00:33:38 +00:00
|
|
|
)))
|
|
|
|
.set(self.ids.crosshair_outer, ui_widgets);
|
|
|
|
Image::new(self.imgs.crosshair_inner)
|
|
|
|
.w_h(21.0 * 2.0, 21.0 * 2.0)
|
|
|
|
.middle_of(self.ids.crosshair_outer)
|
|
|
|
.color(Some(Color::Rgba(1.0, 1.0, 1.0, 0.6)))
|
|
|
|
.set(self.ids.crosshair_inner, ui_widgets);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Max amount the sct font size increases when "flashing"
|
|
|
|
const FLASH_MAX: f32 = 25.0;
|
2020-05-24 06:37:10 +00:00
|
|
|
|
2019-08-07 13:14:26 +00:00
|
|
|
// Get player position.
|
|
|
|
let player_pos = client
|
|
|
|
.state()
|
|
|
|
.ecs()
|
|
|
|
.read_storage::<comp::Pos>()
|
|
|
|
.get(client.entity())
|
|
|
|
.map_or(Vec3::zero(), |pos| pos.0);
|
2020-08-01 20:08:30 +00:00
|
|
|
// SCT Output values are called hp_damage and floater.hp_change
|
|
|
|
// Numbers are currently divided by 10 and rounded
|
2020-01-10 00:33:38 +00:00
|
|
|
if global_state.settings.gameplay.sct {
|
|
|
|
// Render Player SCT numbers
|
|
|
|
let mut player_sct_bg_id_walker = self.ids.player_sct_bgs.walk();
|
|
|
|
let mut player_sct_id_walker = self.ids.player_scts.walk();
|
|
|
|
if let (Some(HpFloaterList { floaters, .. }), Some(stats)) = (
|
|
|
|
hp_floater_lists
|
|
|
|
.get(me)
|
|
|
|
.filter(|fl| !fl.floaters.is_empty()),
|
|
|
|
stats.get(me),
|
|
|
|
) {
|
|
|
|
if global_state.settings.gameplay.sct_player_batch {
|
|
|
|
let number_speed = 100.0; // Player Batched Numbers Speed
|
|
|
|
let player_sct_bg_id = player_sct_bg_id_walker.next(
|
|
|
|
&mut self.ids.player_sct_bgs,
|
|
|
|
&mut ui_widgets.widget_id_generator(),
|
|
|
|
);
|
|
|
|
let player_sct_id = player_sct_id_walker.next(
|
|
|
|
&mut self.ids.player_scts,
|
|
|
|
&mut ui_widgets.widget_id_generator(),
|
|
|
|
);
|
|
|
|
// Calculate total change
|
|
|
|
// Ignores healing
|
|
|
|
let hp_damage = floaters.iter().fold(0, |acc, f| f.hp_change.min(0) + acc);
|
2020-08-01 20:08:30 +00:00
|
|
|
// Divide by 10 to stay in the same dimension as the HP display
|
|
|
|
let hp_dmg_rounded_abs = ((hp_damage + 5) / 10).abs();
|
2020-01-10 00:33:38 +00:00
|
|
|
let max_hp_frac = hp_damage.abs() as f32 / stats.health.maximum() as f32;
|
|
|
|
let timer = floaters
|
|
|
|
.last()
|
|
|
|
.expect("There must be at least one floater")
|
|
|
|
.timer;
|
|
|
|
// Increase font size based on fraction of maximum health
|
|
|
|
// "flashes" by having a larger size in the first 100ms
|
|
|
|
let font_size = 30
|
|
|
|
+ (max_hp_frac * 30.0) as u32
|
|
|
|
+ if timer < 0.1 {
|
|
|
|
(FLASH_MAX * (1.0 - timer / 0.1)) as u32
|
|
|
|
} else {
|
|
|
|
0
|
|
|
|
};
|
|
|
|
// Timer sets the widget offset
|
|
|
|
let y = timer as f64 * number_speed * -1.0;
|
|
|
|
// Timer sets text transparency
|
|
|
|
let hp_fade =
|
|
|
|
((crate::ecs::sys::floater::MY_HP_SHOWTIME - timer) * 0.25) + 0.2;
|
2020-08-01 20:08:30 +00:00
|
|
|
Text::new(&format!("{}", hp_dmg_rounded_abs))
|
2020-01-10 00:33:38 +00:00
|
|
|
.font_size(font_size)
|
2020-02-17 16:22:49 +00:00
|
|
|
.font_id(self.fonts.cyri.conrod_id)
|
2020-01-11 20:31:57 +00:00
|
|
|
.color(if hp_damage < 0 {
|
|
|
|
Color::Rgba(0.0, 0.0, 0.0, hp_fade)
|
|
|
|
} else {
|
|
|
|
Color::Rgba(0.0, 0.0, 0.0, 0.0)
|
|
|
|
})
|
2020-01-10 00:33:38 +00:00
|
|
|
.mid_bottom_with_margin_on(ui_widgets.window, 297.0 + y)
|
|
|
|
.set(player_sct_bg_id, ui_widgets);
|
2020-08-01 20:08:30 +00:00
|
|
|
Text::new(&format!("{}", hp_dmg_rounded_abs))
|
2020-01-10 00:33:38 +00:00
|
|
|
.font_size(font_size)
|
2020-02-17 16:22:49 +00:00
|
|
|
.font_id(self.fonts.cyri.conrod_id)
|
2020-01-10 00:33:38 +00:00
|
|
|
.color(if hp_damage < 0 {
|
|
|
|
Color::Rgba(1.0, 0.1, 0.0, hp_fade)
|
|
|
|
} else {
|
2020-01-11 20:31:57 +00:00
|
|
|
Color::Rgba(0.0, 0.0, 0.0, 0.0)
|
2019-12-30 12:16:35 +00:00
|
|
|
})
|
2020-01-10 00:33:38 +00:00
|
|
|
.mid_bottom_with_margin_on(ui_widgets.window, 300.0 + y)
|
|
|
|
.set(player_sct_id, ui_widgets);
|
|
|
|
};
|
|
|
|
for floater in floaters {
|
|
|
|
// Healing always single numbers so just skip damage when in batch mode
|
|
|
|
|
|
|
|
if global_state.settings.gameplay.sct_player_batch && floater.hp_change < 0
|
|
|
|
{
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
let number_speed = 50.0; // Player Heal Speed
|
|
|
|
let player_sct_bg_id = player_sct_bg_id_walker.next(
|
|
|
|
&mut self.ids.player_sct_bgs,
|
|
|
|
&mut ui_widgets.widget_id_generator(),
|
|
|
|
);
|
|
|
|
let player_sct_id = player_sct_id_walker.next(
|
|
|
|
&mut self.ids.player_scts,
|
|
|
|
&mut ui_widgets.widget_id_generator(),
|
|
|
|
);
|
|
|
|
let max_hp_frac =
|
|
|
|
floater.hp_change.abs() as f32 / stats.health.maximum() as f32;
|
|
|
|
// Increase font size based on fraction of maximum health
|
|
|
|
// "flashes" by having a larger size in the first 100ms
|
|
|
|
let font_size = 30
|
|
|
|
+ (max_hp_frac * 30.0) as u32
|
|
|
|
+ if floater.timer < 0.1 {
|
|
|
|
(FLASH_MAX * (1.0 - floater.timer / 0.1)) as u32
|
|
|
|
} else {
|
|
|
|
0
|
|
|
|
};
|
|
|
|
// Timer sets the widget offset
|
|
|
|
let y = if floater.hp_change < 0 {
|
|
|
|
floater.timer as f64
|
|
|
|
* number_speed
|
|
|
|
* floater.hp_change.signum() as f64
|
|
|
|
//* -1.0
|
|
|
|
+ 300.0
|
|
|
|
- ui_widgets.win_h * 0.5
|
2019-12-30 12:16:35 +00:00
|
|
|
} else {
|
2020-01-10 00:33:38 +00:00
|
|
|
floater.timer as f64
|
|
|
|
* number_speed
|
|
|
|
* floater.hp_change.signum() as f64
|
|
|
|
* -1.0
|
|
|
|
+ 300.0
|
|
|
|
- ui_widgets.win_h * 0.5
|
2019-12-30 12:16:35 +00:00
|
|
|
};
|
2020-01-10 00:33:38 +00:00
|
|
|
// Healing is offset randomly
|
|
|
|
let x = if floater.hp_change < 0 {
|
|
|
|
0.0
|
|
|
|
} else {
|
|
|
|
(floater.rand as f64 - 0.5) * 0.2 * ui_widgets.win_w
|
|
|
|
};
|
|
|
|
// Timer sets text transparency
|
|
|
|
let hp_fade = ((crate::ecs::sys::floater::MY_HP_SHOWTIME - floater.timer)
|
|
|
|
* 0.25)
|
|
|
|
+ 0.2;
|
2020-08-01 20:08:30 +00:00
|
|
|
Text::new(&format!("{}", (floater.hp_change / 10).abs()))
|
2020-01-10 00:33:38 +00:00
|
|
|
.font_size(font_size)
|
2020-02-17 16:22:49 +00:00
|
|
|
.font_id(self.fonts.cyri.conrod_id)
|
2020-01-10 00:33:38 +00:00
|
|
|
.color(Color::Rgba(0.0, 0.0, 0.0, hp_fade))
|
|
|
|
.x_y(x, y - 3.0)
|
|
|
|
.set(player_sct_bg_id, ui_widgets);
|
2020-08-01 20:08:30 +00:00
|
|
|
Text::new(&format!("{}", (floater.hp_change / 10).abs()))
|
2020-01-10 00:33:38 +00:00
|
|
|
.font_size(font_size)
|
2020-02-17 16:22:49 +00:00
|
|
|
.font_id(self.fonts.cyri.conrod_id)
|
2020-01-10 00:33:38 +00:00
|
|
|
.color(if floater.hp_change < 0 {
|
|
|
|
Color::Rgba(1.0, 0.1, 0.0, hp_fade)
|
|
|
|
} else {
|
|
|
|
Color::Rgba(0.1, 1.0, 0.1, hp_fade)
|
|
|
|
})
|
|
|
|
.x_y(x, y)
|
|
|
|
.set(player_sct_id, ui_widgets);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// EXP Numbers
|
|
|
|
if let (Some(floaters), Some(stats)) = (
|
|
|
|
Some(&*ecs.read_resource::<crate::ecs::MyExpFloaterList>())
|
|
|
|
.map(|l| &l.floaters)
|
|
|
|
.filter(|f| !f.is_empty()),
|
|
|
|
stats.get(me),
|
|
|
|
) {
|
|
|
|
// TODO replace with setting
|
|
|
|
let batched_sct = false;
|
|
|
|
if batched_sct {
|
|
|
|
let number_speed = 50.0; // Number Speed for Cumulated EXP
|
|
|
|
let player_sct_bg_id = player_sct_bg_id_walker.next(
|
|
|
|
&mut self.ids.player_sct_bgs,
|
|
|
|
&mut ui_widgets.widget_id_generator(),
|
|
|
|
);
|
|
|
|
let player_sct_id = player_sct_id_walker.next(
|
|
|
|
&mut self.ids.player_scts,
|
|
|
|
&mut ui_widgets.widget_id_generator(),
|
|
|
|
);
|
|
|
|
// Sum xp change
|
|
|
|
let exp_change = floaters.iter().fold(0, |acc, f| f.exp_change + acc);
|
|
|
|
// Can't fail since we filtered out empty lists above
|
|
|
|
let (timer, rand) = floaters
|
|
|
|
.last()
|
|
|
|
.map(|f| (f.timer, f.rand))
|
|
|
|
.expect("Impossible");
|
|
|
|
// Increase font size based on fraction of maximum health
|
|
|
|
// "flashes" by having a larger size in the first 100ms
|
|
|
|
let font_size_xp = 30
|
2020-07-31 05:13:31 +00:00
|
|
|
+ ((exp_change.abs() as f32 / stats.exp.maximum() as f32).min(1.0)
|
|
|
|
* 50.0) as u32
|
2020-01-10 00:33:38 +00:00
|
|
|
+ if timer < 0.1 {
|
|
|
|
(FLASH_MAX * (1.0 - timer / 0.1)) as u32
|
|
|
|
} else {
|
|
|
|
0
|
|
|
|
};
|
|
|
|
|
|
|
|
let y = timer as f64 * number_speed; // Timer sets the widget offset
|
|
|
|
let fade = ((4.0 - timer as f32) * 0.25) + 0.2; // Timer sets text transparency
|
|
|
|
|
|
|
|
Text::new(&format!("{} Exp", exp_change))
|
|
|
|
.font_size(font_size_xp)
|
2020-02-17 16:22:49 +00:00
|
|
|
.font_id(self.fonts.cyri.conrod_id)
|
2020-01-10 00:33:38 +00:00
|
|
|
.color(Color::Rgba(0.0, 0.0, 0.0, fade))
|
|
|
|
.x_y(
|
|
|
|
ui_widgets.win_w * (0.5 * rand.0 as f64 - 0.25),
|
|
|
|
ui_widgets.win_h * (0.15 * rand.1 as f64) + y - 3.0,
|
|
|
|
)
|
|
|
|
.set(player_sct_bg_id, ui_widgets);
|
|
|
|
Text::new(&format!("{} Exp", exp_change))
|
|
|
|
.font_size(font_size_xp)
|
2020-02-17 16:22:49 +00:00
|
|
|
.font_id(self.fonts.cyri.conrod_id)
|
2020-01-10 00:33:38 +00:00
|
|
|
.color(Color::Rgba(0.59, 0.41, 0.67, fade))
|
|
|
|
.x_y(
|
|
|
|
ui_widgets.win_w * (0.5 * rand.0 as f64 - 0.25),
|
|
|
|
ui_widgets.win_h * (0.15 * rand.1 as f64) + y,
|
|
|
|
)
|
|
|
|
.set(player_sct_id, ui_widgets);
|
|
|
|
} else {
|
|
|
|
for floater in floaters {
|
|
|
|
let number_speed = 50.0; // Number Speed for Single EXP
|
|
|
|
let player_sct_bg_id = player_sct_bg_id_walker.next(
|
|
|
|
&mut self.ids.player_sct_bgs,
|
|
|
|
&mut ui_widgets.widget_id_generator(),
|
|
|
|
);
|
|
|
|
let player_sct_id = player_sct_id_walker.next(
|
|
|
|
&mut self.ids.player_scts,
|
|
|
|
&mut ui_widgets.widget_id_generator(),
|
|
|
|
);
|
|
|
|
// Increase font size based on fraction of maximum health
|
|
|
|
// "flashes" by having a larger size in the first 100ms
|
|
|
|
let font_size_xp = 30
|
2020-07-31 05:13:31 +00:00
|
|
|
+ ((floater.exp_change.abs() as f32 / stats.exp.maximum() as f32)
|
|
|
|
.min(1.0)
|
2020-01-10 00:33:38 +00:00
|
|
|
* 50.0) as u32
|
|
|
|
+ if floater.timer < 0.1 {
|
|
|
|
(FLASH_MAX * (1.0 - floater.timer / 0.1)) as u32
|
|
|
|
} else {
|
|
|
|
0
|
|
|
|
};
|
|
|
|
|
|
|
|
let y = floater.timer as f64 * number_speed; // Timer sets the widget offset
|
|
|
|
let fade = ((4.0 - floater.timer as f32) * 0.25) + 0.2; // Timer sets text transparency
|
|
|
|
|
|
|
|
Text::new(&format!("{} Exp", floater.exp_change))
|
|
|
|
.font_size(font_size_xp)
|
2020-02-17 16:22:49 +00:00
|
|
|
.font_id(self.fonts.cyri.conrod_id)
|
2020-01-10 00:33:38 +00:00
|
|
|
.color(Color::Rgba(0.0, 0.0, 0.0, fade))
|
|
|
|
.x_y(
|
|
|
|
ui_widgets.win_w * (0.5 * floater.rand.0 as f64 - 0.25),
|
|
|
|
ui_widgets.win_h * (0.15 * floater.rand.1 as f64) + y - 3.0,
|
|
|
|
)
|
|
|
|
.set(player_sct_bg_id, ui_widgets);
|
|
|
|
Text::new(&format!("{} Exp", floater.exp_change))
|
|
|
|
.font_size(font_size_xp)
|
2020-02-17 16:22:49 +00:00
|
|
|
.font_id(self.fonts.cyri.conrod_id)
|
2020-01-10 00:33:38 +00:00
|
|
|
.color(Color::Rgba(0.59, 0.41, 0.67, fade))
|
|
|
|
.x_y(
|
|
|
|
ui_widgets.win_w * (0.5 * floater.rand.0 as f64 - 0.25),
|
|
|
|
ui_widgets.win_h * (0.15 * floater.rand.1 as f64) + y,
|
|
|
|
)
|
|
|
|
.set(player_sct_id, ui_widgets);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-06-04 07:11:35 +00:00
|
|
|
// Pop speech bubbles
|
2020-06-11 05:16:42 +00:00
|
|
|
let now = Instant::now();
|
2020-06-04 07:11:35 +00:00
|
|
|
self.speech_bubbles
|
2020-06-11 05:16:42 +00:00
|
|
|
.retain(|_uid, bubble| bubble.timeout > now);
|
2020-06-04 07:11:35 +00:00
|
|
|
|
|
|
|
// Push speech bubbles
|
|
|
|
for msg in self.new_messages.iter() {
|
|
|
|
if let Some((bubble, uid)) = msg.to_bubble() {
|
|
|
|
self.speech_bubbles.insert(uid, bubble);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-05-24 06:37:10 +00:00
|
|
|
let mut overhead_walker = self.ids.overheads.walk();
|
2020-07-29 13:21:12 +00:00
|
|
|
let mut overitem_walker = self.ids.overitems.walk();
|
2020-05-24 06:37:10 +00:00
|
|
|
let mut sct_walker = self.ids.scts.walk();
|
|
|
|
let mut sct_bg_walker = self.ids.sct_bgs.walk();
|
|
|
|
|
2020-07-29 13:21:12 +00:00
|
|
|
// Render overitem name
|
|
|
|
for (pos, item, distance) in (&entities, &pos, &items)
|
|
|
|
.join()
|
|
|
|
.map(|(_, pos, item)| (pos, item, pos.0.distance_squared(player_pos)))
|
|
|
|
.filter(|(_, _, distance)| distance < &common::comp::MAX_PICKUP_RANGE_SQR)
|
|
|
|
{
|
|
|
|
let overitem_id = overitem_walker.next(
|
|
|
|
&mut self.ids.overitems,
|
|
|
|
&mut ui_widgets.widget_id_generator(),
|
|
|
|
);
|
|
|
|
let ingame_pos = pos.0 + Vec3::unit_z() * 1.2;
|
|
|
|
|
|
|
|
// Item name
|
|
|
|
overitem::Overitem::new(&item.name(), &distance, &self.fonts)
|
|
|
|
.x_y(0.0, 100.0)
|
|
|
|
.position_ingame(ingame_pos)
|
|
|
|
.set(overitem_id, ui_widgets);
|
|
|
|
}
|
|
|
|
|
2020-05-24 06:37:10 +00:00
|
|
|
// Render overhead name tags and health bars
|
2020-07-12 03:12:03 +00:00
|
|
|
for (pos, name, stats, energy, height_offset, hpfl, uid, in_group) in (
|
2020-01-10 00:33:38 +00:00
|
|
|
&entities,
|
|
|
|
&pos,
|
|
|
|
interpolated.maybe(),
|
|
|
|
&stats,
|
2020-07-05 12:39:28 +00:00
|
|
|
energy.maybe(),
|
2020-01-10 00:33:38 +00:00
|
|
|
players.maybe(),
|
|
|
|
scales.maybe(),
|
2020-02-05 01:30:31 +00:00
|
|
|
&bodies,
|
2020-01-25 03:06:41 +00:00
|
|
|
&hp_floater_lists,
|
2020-06-04 07:11:35 +00:00
|
|
|
&uids,
|
2020-01-10 00:33:38 +00:00
|
|
|
)
|
|
|
|
.join()
|
2020-07-12 03:12:03 +00:00
|
|
|
.map(|(a, b, c, d, e, f, g, h, i, uid)| {
|
|
|
|
(
|
|
|
|
a,
|
|
|
|
b,
|
|
|
|
c,
|
|
|
|
d,
|
|
|
|
e,
|
|
|
|
f,
|
|
|
|
g,
|
|
|
|
h,
|
|
|
|
i,
|
|
|
|
uid,
|
2020-07-19 21:49:18 +00:00
|
|
|
client.group_members().contains_key(uid),
|
2020-07-12 03:12:03 +00:00
|
|
|
)
|
|
|
|
})
|
2020-07-12 04:04:13 +00:00
|
|
|
.filter(|(entity, pos, _, stats, _, _, _, _, hpfl, _, in_group)| {
|
2020-07-12 03:12:03 +00:00
|
|
|
*entity != me && !stats.is_dead
|
2020-04-27 03:40:56 +00:00
|
|
|
&& (stats.health.current() != stats.health.maximum()
|
|
|
|
|| info.target_entity.map_or(false, |e| e == *entity)
|
2020-07-12 00:39:50 +00:00
|
|
|
|| info.selected_entity.map_or(false, |s| s.0 == *entity)
|
2020-07-12 03:12:03 +00:00
|
|
|
|| *in_group
|
|
|
|
)
|
|
|
|
// Don't show outside a certain range
|
|
|
|
&& pos.0.distance_squared(player_pos)
|
|
|
|
< (if *in_group
|
|
|
|
{
|
|
|
|
NAMETAG_GROUP_RANGE
|
|
|
|
} else if hpfl
|
2020-01-25 03:06:41 +00:00
|
|
|
.time_since_last_dmg_by_me
|
|
|
|
.map_or(false, |t| t < NAMETAG_DMG_TIME)
|
|
|
|
{
|
|
|
|
NAMETAG_DMG_RANGE
|
|
|
|
} else {
|
|
|
|
NAMETAG_RANGE
|
2020-01-10 00:33:38 +00:00
|
|
|
})
|
2020-01-25 03:06:41 +00:00
|
|
|
.powi(2)
|
2020-01-10 00:33:38 +00:00
|
|
|
})
|
2020-07-12 03:12:03 +00:00
|
|
|
.map(
|
|
|
|
|(
|
|
|
|
_,
|
|
|
|
pos,
|
|
|
|
interpolated,
|
2020-05-24 06:37:10 +00:00
|
|
|
stats,
|
|
|
|
energy,
|
2020-07-12 03:12:03 +00:00
|
|
|
player,
|
|
|
|
scale,
|
|
|
|
body,
|
2020-05-24 06:37:10 +00:00
|
|
|
hpfl,
|
2020-06-04 07:11:35 +00:00
|
|
|
uid,
|
2020-07-12 03:12:03 +00:00
|
|
|
in_group,
|
|
|
|
)| {
|
|
|
|
// TODO: This is temporary
|
|
|
|
// If the player used the default character name display their name instead
|
|
|
|
let name = if stats.name == "Character Name" {
|
|
|
|
player.map_or(&stats.name, |p| &p.alias)
|
|
|
|
} else {
|
|
|
|
&stats.name
|
|
|
|
};
|
|
|
|
(
|
|
|
|
interpolated.map_or(pos.0, |i| i.pos),
|
|
|
|
name,
|
|
|
|
stats,
|
|
|
|
energy,
|
|
|
|
// TODO: when body.height() is more accurate remove the 2.0
|
|
|
|
body.height() * 2.0 * scale.map_or(1.0, |s| s.0),
|
|
|
|
hpfl,
|
|
|
|
uid,
|
|
|
|
in_group,
|
|
|
|
)
|
|
|
|
},
|
|
|
|
)
|
2019-12-30 12:16:35 +00:00
|
|
|
{
|
2020-06-04 07:11:35 +00:00
|
|
|
let bubble = self.speech_bubbles.get(uid);
|
|
|
|
|
2020-05-24 06:37:10 +00:00
|
|
|
let overhead_id = overhead_walker.next(
|
|
|
|
&mut self.ids.overheads,
|
2019-12-30 12:16:35 +00:00
|
|
|
&mut ui_widgets.widget_id_generator(),
|
|
|
|
);
|
2020-02-05 01:30:31 +00:00
|
|
|
let ingame_pos = pos + Vec3::unit_z() * height_offset;
|
|
|
|
|
2020-05-25 01:29:47 +00:00
|
|
|
// Speech bubble, name, level, and hp bars
|
2020-05-24 06:37:10 +00:00
|
|
|
overhead::Overhead::new(
|
|
|
|
&name,
|
2020-05-24 22:18:41 +00:00
|
|
|
bubble,
|
2020-05-24 06:37:10 +00:00
|
|
|
stats,
|
|
|
|
energy,
|
|
|
|
own_level,
|
2020-07-12 03:12:03 +00:00
|
|
|
in_group,
|
2020-05-25 01:29:47 +00:00
|
|
|
&global_state.settings.gameplay,
|
2020-05-24 06:37:10 +00:00
|
|
|
self.pulse,
|
2020-05-26 00:11:22 +00:00
|
|
|
&self.voxygen_i18n,
|
2020-05-24 06:37:10 +00:00
|
|
|
&self.imgs,
|
|
|
|
&self.fonts,
|
|
|
|
)
|
|
|
|
.x_y(0.0, 100.0)
|
|
|
|
.position_ingame(ingame_pos)
|
|
|
|
.set(overhead_id, ui_widgets);
|
|
|
|
|
|
|
|
// Enemy SCT
|
|
|
|
if global_state.settings.gameplay.sct && !hpfl.floaters.is_empty() {
|
|
|
|
let floaters = &hpfl.floaters;
|
|
|
|
|
|
|
|
// Colors
|
|
|
|
const WHITE: Rgb<f32> = Rgb::new(1.0, 0.9, 0.8);
|
|
|
|
const LIGHT_OR: Rgb<f32> = Rgb::new(1.0, 0.925, 0.749);
|
|
|
|
const LIGHT_MED_OR: Rgb<f32> = Rgb::new(1.0, 0.85, 0.498);
|
|
|
|
const MED_OR: Rgb<f32> = Rgb::new(1.0, 0.776, 0.247);
|
|
|
|
const DARK_ORANGE: Rgb<f32> = Rgb::new(1.0, 0.7, 0.0);
|
|
|
|
const RED_ORANGE: Rgb<f32> = Rgb::new(1.0, 0.349, 0.0);
|
|
|
|
const DAMAGE_COLORS: [Rgb<f32>; 6] = [
|
|
|
|
WHITE,
|
|
|
|
LIGHT_OR,
|
|
|
|
LIGHT_MED_OR,
|
|
|
|
MED_OR,
|
|
|
|
DARK_ORANGE,
|
|
|
|
RED_ORANGE,
|
|
|
|
];
|
|
|
|
// Largest value that select the first color is 40, then it shifts colors
|
|
|
|
// every 5
|
|
|
|
let font_col = |font_size: u32| {
|
|
|
|
DAMAGE_COLORS[(font_size.saturating_sub(36) / 5).min(5) as usize]
|
|
|
|
};
|
|
|
|
|
|
|
|
if global_state.settings.gameplay.sct_damage_batch {
|
|
|
|
let number_speed = 50.0; // Damage number speed
|
|
|
|
let sct_id = sct_walker
|
|
|
|
.next(&mut self.ids.scts, &mut ui_widgets.widget_id_generator());
|
|
|
|
let sct_bg_id = sct_bg_walker
|
|
|
|
.next(&mut self.ids.sct_bgs, &mut ui_widgets.widget_id_generator());
|
|
|
|
// Calculate total change
|
|
|
|
// Ignores healing
|
|
|
|
let hp_damage = floaters.iter().fold(0, |acc, f| {
|
|
|
|
if f.hp_change < 0 {
|
|
|
|
acc + f.hp_change
|
|
|
|
} else {
|
|
|
|
acc
|
|
|
|
}
|
|
|
|
});
|
2020-08-01 20:08:30 +00:00
|
|
|
// Divide by 10 to stay in the same dimension as the HP display
|
|
|
|
let hp_dmg_rounded_abs = ((hp_damage + 5) / 10).abs();
|
2020-05-24 06:37:10 +00:00
|
|
|
let max_hp_frac = hp_damage.abs() as f32 / stats.health.maximum() as f32;
|
|
|
|
let timer = floaters
|
|
|
|
.last()
|
|
|
|
.expect("There must be at least one floater")
|
|
|
|
.timer;
|
|
|
|
// Increase font size based on fraction of maximum health
|
|
|
|
// "flashes" by having a larger size in the first 100ms
|
|
|
|
let font_size = 30
|
|
|
|
+ (max_hp_frac * 30.0) as u32
|
|
|
|
+ if timer < 0.1 {
|
|
|
|
(FLASH_MAX * (1.0 - timer / 0.1)) as u32
|
|
|
|
} else {
|
|
|
|
0
|
|
|
|
};
|
|
|
|
let font_col = font_col(font_size);
|
|
|
|
// Timer sets the widget offset
|
|
|
|
let y = (timer as f64 / crate::ecs::sys::floater::HP_SHOWTIME as f64
|
|
|
|
* number_speed)
|
|
|
|
+ 100.0;
|
|
|
|
// Timer sets text transparency
|
|
|
|
let fade = ((crate::ecs::sys::floater::HP_SHOWTIME - timer) * 0.25) + 0.2;
|
|
|
|
|
2020-08-01 20:08:30 +00:00
|
|
|
Text::new(&format!("{}", hp_dmg_rounded_abs))
|
2020-05-24 06:37:10 +00:00
|
|
|
.font_size(font_size)
|
|
|
|
.font_id(self.fonts.cyri.conrod_id)
|
|
|
|
.color(Color::Rgba(0.0, 0.0, 0.0, fade))
|
|
|
|
.x_y(0.0, y - 3.0)
|
|
|
|
.position_ingame(ingame_pos)
|
|
|
|
.set(sct_bg_id, ui_widgets);
|
2020-08-01 20:08:30 +00:00
|
|
|
Text::new(&format!("{}", hp_dmg_rounded_abs))
|
2020-05-24 06:37:10 +00:00
|
|
|
.font_size(font_size)
|
|
|
|
.font_id(self.fonts.cyri.conrod_id)
|
|
|
|
.x_y(0.0, y)
|
|
|
|
.color(if hp_damage < 0 {
|
|
|
|
Color::Rgba(font_col.r, font_col.g, font_col.b, fade)
|
|
|
|
} else {
|
|
|
|
Color::Rgba(0.1, 1.0, 0.1, fade)
|
|
|
|
})
|
|
|
|
.position_ingame(ingame_pos)
|
|
|
|
.set(sct_id, ui_widgets);
|
2019-12-30 12:16:35 +00:00
|
|
|
} else {
|
2020-05-24 06:37:10 +00:00
|
|
|
for floater in floaters {
|
|
|
|
let number_speed = 250.0; // Single Numbers Speed
|
|
|
|
let sct_id = sct_walker
|
|
|
|
.next(&mut self.ids.scts, &mut ui_widgets.widget_id_generator());
|
|
|
|
let sct_bg_id = sct_bg_walker
|
|
|
|
.next(&mut self.ids.sct_bgs, &mut ui_widgets.widget_id_generator());
|
|
|
|
// Calculate total change
|
|
|
|
let max_hp_frac =
|
|
|
|
floater.hp_change.abs() as f32 / stats.health.maximum() as f32;
|
|
|
|
// Increase font size based on fraction of maximum health
|
|
|
|
// "flashes" by having a larger size in the first 100ms
|
|
|
|
let font_size = 30
|
|
|
|
+ (max_hp_frac * 30.0) as u32
|
|
|
|
+ if floater.timer < 0.1 {
|
|
|
|
(FLASH_MAX * (1.0 - floater.timer / 0.1)) as u32
|
|
|
|
} else {
|
|
|
|
0
|
|
|
|
};
|
|
|
|
let font_col = font_col(font_size);
|
|
|
|
// Timer sets the widget offset
|
|
|
|
let y = (floater.timer as f64
|
|
|
|
/ crate::ecs::sys::floater::HP_SHOWTIME as f64
|
|
|
|
* number_speed)
|
|
|
|
+ 100.0;
|
|
|
|
// Timer sets text transparency
|
|
|
|
let fade = ((crate::ecs::sys::floater::HP_SHOWTIME - floater.timer)
|
|
|
|
* 0.25)
|
|
|
|
+ 0.2;
|
|
|
|
|
2020-08-01 20:08:30 +00:00
|
|
|
Text::new(&format!("{}", (floater.hp_change / 10).abs()))
|
2020-05-24 06:37:10 +00:00
|
|
|
.font_size(font_size)
|
|
|
|
.font_id(self.fonts.cyri.conrod_id)
|
|
|
|
.color(if floater.hp_change < 0 {
|
|
|
|
Color::Rgba(0.0, 0.0, 0.0, fade)
|
|
|
|
} else {
|
|
|
|
Color::Rgba(0.0, 0.0, 0.0, 1.0)
|
|
|
|
})
|
|
|
|
.x_y(0.0, y - 3.0)
|
|
|
|
.position_ingame(ingame_pos)
|
|
|
|
.set(sct_bg_id, ui_widgets);
|
2020-08-01 20:08:30 +00:00
|
|
|
Text::new(&format!("{}", (floater.hp_change / 10).abs()))
|
2020-05-24 06:37:10 +00:00
|
|
|
.font_size(font_size)
|
|
|
|
.font_id(self.fonts.cyri.conrod_id)
|
|
|
|
.x_y(0.0, y)
|
|
|
|
.color(if floater.hp_change < 0 {
|
|
|
|
Color::Rgba(font_col.r, font_col.g, font_col.b, fade)
|
|
|
|
} else {
|
|
|
|
Color::Rgba(0.1, 1.0, 0.1, 1.0)
|
|
|
|
})
|
|
|
|
.position_ingame(ingame_pos)
|
|
|
|
.set(sct_id, ui_widgets);
|
|
|
|
}
|
|
|
|
}
|
2019-12-30 12:16:35 +00:00
|
|
|
}
|
2019-05-14 06:43:07 +00:00
|
|
|
}
|
2019-05-15 00:04:58 +00:00
|
|
|
}
|
2020-01-10 00:33:38 +00:00
|
|
|
|
2020-06-03 17:59:09 +00:00
|
|
|
// Temporary Example Quest
|
|
|
|
if self.show.intro && !self.show.esc_menu {
|
2019-10-23 19:40:45 +00:00
|
|
|
match global_state.settings.gameplay.intro_show {
|
|
|
|
Intro::Show => {
|
2020-06-03 17:59:09 +00:00
|
|
|
if self.pulse > 20.0 {
|
|
|
|
self.show.want_grab = false;
|
|
|
|
let quest_headline = &self.voxygen_i18n.get("hud.temp_quest_headline");
|
|
|
|
let quest_text = &self.voxygen_i18n.get("hud.temp_quest_text");
|
|
|
|
Image::new(self.imgs.quest_bg)
|
|
|
|
.w_h(404.0, 858.0)
|
|
|
|
.middle_of(ui_widgets.window)
|
|
|
|
.set(self.ids.quest_bg, ui_widgets);
|
|
|
|
|
|
|
|
Text::new(quest_headline)
|
|
|
|
.mid_top_with_margin_on(self.ids.quest_bg, 310.0)
|
|
|
|
.font_size(self.fonts.cyri.scale(30))
|
|
|
|
.font_id(self.fonts.cyri.conrod_id)
|
|
|
|
.color(TEXT_BG)
|
|
|
|
.set(self.ids.q_headline_bg, ui_widgets);
|
|
|
|
Text::new(quest_headline)
|
|
|
|
.bottom_left_with_margins_on(self.ids.q_headline_bg, 1.0, 1.0)
|
|
|
|
.font_size(self.fonts.cyri.scale(30))
|
|
|
|
.font_id(self.fonts.cyri.conrod_id)
|
|
|
|
.color(TEXT_COLOR)
|
|
|
|
.set(self.ids.q_headline, ui_widgets);
|
|
|
|
|
|
|
|
Text::new(quest_text)
|
|
|
|
.down_from(self.ids.q_headline_bg, 40.0)
|
|
|
|
.font_size(self.fonts.cyri.scale(17))
|
|
|
|
.font_id(self.fonts.cyri.conrod_id)
|
|
|
|
.color(TEXT_BG)
|
|
|
|
.set(self.ids.q_text_bg, ui_widgets);
|
|
|
|
Text::new(quest_text)
|
|
|
|
.bottom_left_with_margins_on(self.ids.q_text_bg, 1.0, 1.0)
|
|
|
|
.font_size(self.fonts.cyri.scale(17))
|
|
|
|
.font_id(self.fonts.cyri.conrod_id)
|
|
|
|
.color(TEXT_COLOR)
|
|
|
|
.set(self.ids.q_text, ui_widgets);
|
|
|
|
|
|
|
|
if Button::image(self.imgs.button)
|
|
|
|
.w_h(212.0, 52.0)
|
|
|
|
.hover_image(self.imgs.button_hover)
|
|
|
|
.press_image(self.imgs.button_press)
|
|
|
|
.mid_bottom_with_margin_on(self.ids.q_text_bg, -120.0)
|
|
|
|
.label(&self.voxygen_i18n.get("common.accept"))
|
|
|
|
.label_font_id(self.fonts.cyri.conrod_id)
|
|
|
|
.label_font_size(self.fonts.cyri.scale(22))
|
|
|
|
.label_color(TEXT_COLOR)
|
2020-06-03 19:32:54 +00:00
|
|
|
.label_y(conrod_core::position::Relative::Scalar(2.0))
|
2020-06-03 17:59:09 +00:00
|
|
|
.set(self.ids.accept_button, ui_widgets)
|
|
|
|
.was_clicked()
|
|
|
|
{
|
2019-10-23 19:40:45 +00:00
|
|
|
self.show.intro = !self.show.intro;
|
2019-10-24 18:21:17 +00:00
|
|
|
events.push(Event::Intro(Intro::Never));
|
2020-06-03 17:59:09 +00:00
|
|
|
self.show.want_grab = true;
|
2019-10-24 18:21:17 +00:00
|
|
|
}
|
2020-06-03 17:59:09 +00:00
|
|
|
}
|
2020-02-01 20:39:39 +00:00
|
|
|
},
|
2020-06-03 19:32:54 +00:00
|
|
|
Intro::Never => {
|
|
|
|
self.show.intro = false;
|
|
|
|
},
|
2019-10-23 19:40:45 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-05-17 09:22:32 +00:00
|
|
|
// Display debug window.
|
2020-01-10 00:33:38 +00:00
|
|
|
if global_state.settings.gameplay.toggle_debug {
|
2019-04-26 16:13:30 +00:00
|
|
|
// Alpha Version
|
2019-06-28 12:08:12 +00:00
|
|
|
Text::new(&version)
|
2019-04-26 16:13:30 +00:00
|
|
|
.top_left_with_margins_on(ui_widgets.window, 5.0, 5.0)
|
2020-01-26 19:29:46 +00:00
|
|
|
.font_size(self.fonts.cyri.scale(14))
|
|
|
|
.font_id(self.fonts.cyri.conrod_id)
|
2019-04-26 16:13:30 +00:00
|
|
|
.color(TEXT_COLOR)
|
|
|
|
.set(self.ids.version, ui_widgets);
|
2019-06-23 19:49:15 +00:00
|
|
|
// Ticks per second
|
2019-08-22 17:44:35 +00:00
|
|
|
Text::new(&format!("FPS: {:.0}", debug_info.tps))
|
2019-04-22 18:47:22 +00:00
|
|
|
.color(TEXT_COLOR)
|
2019-04-26 16:13:30 +00:00
|
|
|
.down_from(self.ids.version, 5.0)
|
2020-01-26 19:29:46 +00:00
|
|
|
.font_id(self.fonts.cyri.conrod_id)
|
|
|
|
.font_size(self.fonts.cyri.scale(14))
|
2019-04-22 18:47:22 +00:00
|
|
|
.set(self.ids.fps_counter, ui_widgets);
|
2019-06-23 19:49:15 +00:00
|
|
|
// Ping
|
2019-08-22 17:44:35 +00:00
|
|
|
Text::new(&format!("Ping: {:.0}ms", debug_info.ping_ms))
|
2019-05-23 08:18:25 +00:00
|
|
|
.color(TEXT_COLOR)
|
|
|
|
.down_from(self.ids.fps_counter, 5.0)
|
2020-01-26 19:29:46 +00:00
|
|
|
.font_id(self.fonts.cyri.conrod_id)
|
|
|
|
.font_size(self.fonts.cyri.scale(14))
|
2019-05-23 08:18:25 +00:00
|
|
|
.set(self.ids.ping, ui_widgets);
|
2019-08-06 21:51:13 +00:00
|
|
|
// Player's position
|
2019-05-28 19:40:50 +00:00
|
|
|
let coordinates_text = match debug_info.coordinates {
|
2019-08-22 17:44:35 +00:00
|
|
|
Some(coordinates) => format!(
|
|
|
|
"Coordinates: ({:.0}, {:.0}, {:.0})",
|
|
|
|
coordinates.0.x, coordinates.0.y, coordinates.0.z,
|
|
|
|
),
|
2019-05-28 19:40:50 +00:00
|
|
|
None => "Player has no Pos component".to_owned(),
|
|
|
|
};
|
|
|
|
Text::new(&coordinates_text)
|
2019-05-28 18:23:24 +00:00
|
|
|
.color(TEXT_COLOR)
|
|
|
|
.down_from(self.ids.ping, 5.0)
|
2020-01-26 19:29:46 +00:00
|
|
|
.font_id(self.fonts.cyri.conrod_id)
|
|
|
|
.font_size(self.fonts.cyri.scale(14))
|
2019-05-28 18:23:24 +00:00
|
|
|
.set(self.ids.coordinates, ui_widgets);
|
2019-08-07 02:26:24 +00:00
|
|
|
// Player's velocity
|
2019-08-06 21:51:13 +00:00
|
|
|
let velocity_text = match debug_info.velocity {
|
2019-08-22 19:26:35 +00:00
|
|
|
Some(velocity) => format!(
|
|
|
|
"Velocity: ({:.1}, {:.1}, {:.1}) [{:.1} u/s]",
|
|
|
|
velocity.0.x,
|
|
|
|
velocity.0.y,
|
|
|
|
velocity.0.z,
|
|
|
|
velocity.0.magnitude()
|
|
|
|
),
|
2019-08-06 21:51:13 +00:00
|
|
|
None => "Player has no Vel component".to_owned(),
|
|
|
|
};
|
|
|
|
Text::new(&velocity_text)
|
|
|
|
.color(TEXT_COLOR)
|
|
|
|
.down_from(self.ids.coordinates, 5.0)
|
2020-01-26 19:29:46 +00:00
|
|
|
.font_id(self.fonts.cyri.conrod_id)
|
|
|
|
.font_size(self.fonts.cyri.scale(14))
|
2019-08-06 21:51:13 +00:00
|
|
|
.set(self.ids.velocity, ui_widgets);
|
2020-04-25 00:30:20 +00:00
|
|
|
// Player's orientation vector
|
|
|
|
let orientation_text = match debug_info.ori {
|
|
|
|
Some(ori) => format!(
|
|
|
|
"Orientation: ({:.1}, {:.1}, {:.1})",
|
|
|
|
ori.0.x, ori.0.y, ori.0.z,
|
|
|
|
),
|
|
|
|
None => "Player has no Ori component".to_owned(),
|
|
|
|
};
|
|
|
|
Text::new(&orientation_text)
|
|
|
|
.color(TEXT_COLOR)
|
|
|
|
.down_from(self.ids.velocity, 5.0)
|
|
|
|
.font_id(self.fonts.cyri.conrod_id)
|
|
|
|
.font_size(self.fonts.cyri.scale(14))
|
|
|
|
.set(self.ids.orientation, ui_widgets);
|
2019-06-23 19:49:15 +00:00
|
|
|
// Loaded distance
|
|
|
|
Text::new(&format!(
|
2020-01-12 11:09:37 +00:00
|
|
|
"View distance: {:.2} blocks ({:.2} chunks)",
|
|
|
|
client.loaded_distance(),
|
|
|
|
client.loaded_distance() / TerrainChunk::RECT_SIZE.x as f32,
|
2019-06-23 19:49:15 +00:00
|
|
|
))
|
|
|
|
.color(TEXT_COLOR)
|
2020-04-25 00:30:20 +00:00
|
|
|
.down_from(self.ids.orientation, 5.0)
|
2020-01-26 19:29:46 +00:00
|
|
|
.font_id(self.fonts.cyri.conrod_id)
|
|
|
|
.font_size(self.fonts.cyri.scale(14))
|
2019-06-23 19:49:15 +00:00
|
|
|
.set(self.ids.loaded_distance, ui_widgets);
|
2019-09-01 19:04:03 +00:00
|
|
|
// Time
|
|
|
|
let time_in_seconds = client.state().get_time_of_day();
|
|
|
|
let current_time = NaiveTime::from_num_seconds_from_midnight(
|
|
|
|
// Wraps around back to 0s if it exceeds 24 hours (24 hours = 86400s)
|
|
|
|
(time_in_seconds as u64 % 86400) as u32,
|
|
|
|
0,
|
|
|
|
);
|
|
|
|
Text::new(&format!(
|
|
|
|
"Time: {}",
|
|
|
|
current_time.format("%H:%M").to_string()
|
|
|
|
))
|
|
|
|
.color(TEXT_COLOR)
|
|
|
|
.down_from(self.ids.loaded_distance, 5.0)
|
2020-01-26 19:29:46 +00:00
|
|
|
.font_id(self.fonts.cyri.conrod_id)
|
|
|
|
.font_size(self.fonts.cyri.scale(14))
|
2019-09-01 19:04:03 +00:00
|
|
|
.set(self.ids.time, ui_widgets);
|
2019-11-19 15:13:33 +00:00
|
|
|
|
2019-11-29 06:04:37 +00:00
|
|
|
// Number of entities
|
|
|
|
let entity_count = client.state().ecs().entities().join().count();
|
|
|
|
Text::new(&format!("Entity count: {}", entity_count))
|
|
|
|
.color(TEXT_COLOR)
|
|
|
|
.down_from(self.ids.time, 5.0)
|
2020-01-26 19:29:46 +00:00
|
|
|
.font_id(self.fonts.cyri.conrod_id)
|
|
|
|
.font_size(self.fonts.cyri.scale(14))
|
2019-11-29 06:04:37 +00:00
|
|
|
.set(self.ids.entity_count, ui_widgets);
|
2020-01-08 17:09:54 +00:00
|
|
|
|
2019-11-19 15:13:33 +00:00
|
|
|
// Number of chunks
|
|
|
|
Text::new(&format!(
|
|
|
|
"Chunks: {} ({} visible)",
|
|
|
|
debug_info.num_chunks, debug_info.num_visible_chunks,
|
|
|
|
))
|
|
|
|
.color(TEXT_COLOR)
|
|
|
|
.down_from(self.ids.entity_count, 5.0)
|
2020-01-26 19:29:46 +00:00
|
|
|
.font_id(self.fonts.cyri.conrod_id)
|
|
|
|
.font_size(self.fonts.cyri.scale(14))
|
2019-11-19 15:13:33 +00:00
|
|
|
.set(self.ids.num_chunks, ui_widgets);
|
|
|
|
|
|
|
|
// Number of figures
|
|
|
|
Text::new(&format!(
|
|
|
|
"Figures: {} ({} visible)",
|
|
|
|
debug_info.num_figures, debug_info.num_figures_visible,
|
|
|
|
))
|
|
|
|
.color(TEXT_COLOR)
|
|
|
|
.down_from(self.ids.num_chunks, 5.0)
|
2020-01-26 19:29:46 +00:00
|
|
|
.font_id(self.fonts.cyri.conrod_id)
|
|
|
|
.font_size(self.fonts.cyri.scale(14))
|
2019-11-19 15:13:33 +00:00
|
|
|
.set(self.ids.num_figures, ui_widgets);
|
2019-10-06 19:19:08 +00:00
|
|
|
|
|
|
|
// Help Window
|
2020-04-08 17:36:37 +00:00
|
|
|
if let Some(help_key) = global_state.settings.controls.get_binding(GameInput::Help) {
|
|
|
|
Text::new(
|
|
|
|
&self
|
|
|
|
.voxygen_i18n
|
|
|
|
.get("hud.press_key_to_toggle_keybindings_fmt")
|
|
|
|
.replace("{key}", help_key.to_string().as_str()),
|
|
|
|
)
|
|
|
|
.color(TEXT_COLOR)
|
|
|
|
.down_from(self.ids.num_figures, 5.0)
|
|
|
|
.font_id(self.fonts.cyri.conrod_id)
|
|
|
|
.font_size(self.fonts.cyri.scale(14))
|
|
|
|
.set(self.ids.help_info, ui_widgets);
|
|
|
|
}
|
2020-01-10 00:33:38 +00:00
|
|
|
// Info about Debug Shortcut
|
2020-04-08 17:36:37 +00:00
|
|
|
if let Some(toggle_debug_key) = global_state
|
|
|
|
.settings
|
|
|
|
.controls
|
|
|
|
.get_binding(GameInput::ToggleDebug)
|
|
|
|
{
|
|
|
|
Text::new(
|
|
|
|
&self
|
|
|
|
.voxygen_i18n
|
|
|
|
.get("hud.press_key_to_toggle_debug_info_fmt")
|
|
|
|
.replace("{key}", toggle_debug_key.to_string().as_str()),
|
|
|
|
)
|
|
|
|
.color(TEXT_COLOR)
|
|
|
|
.down_from(self.ids.help_info, 5.0)
|
|
|
|
.font_id(self.fonts.cyri.conrod_id)
|
|
|
|
.font_size(self.fonts.cyri.scale(14))
|
|
|
|
.set(self.ids.debug_info, ui_widgets);
|
|
|
|
}
|
2020-01-10 00:33:38 +00:00
|
|
|
} else {
|
|
|
|
// Help Window
|
2020-04-08 17:36:37 +00:00
|
|
|
if let Some(help_key) = global_state.settings.controls.get_binding(GameInput::Help) {
|
|
|
|
Text::new(
|
|
|
|
&self
|
|
|
|
.voxygen_i18n
|
|
|
|
.get("hud.press_key_to_show_keybindings_fmt")
|
|
|
|
.replace("{key}", help_key.to_string().as_str()),
|
|
|
|
)
|
|
|
|
.color(TEXT_COLOR)
|
|
|
|
.top_left_with_margins_on(ui_widgets.window, 5.0, 5.0)
|
|
|
|
.font_id(self.fonts.cyri.conrod_id)
|
|
|
|
.font_size(self.fonts.cyri.scale(16))
|
|
|
|
.set(self.ids.help_info, ui_widgets);
|
|
|
|
}
|
2020-01-10 00:33:38 +00:00
|
|
|
// Info about Debug Shortcut
|
2020-04-08 17:36:37 +00:00
|
|
|
if let Some(toggle_debug_key) = global_state
|
|
|
|
.settings
|
|
|
|
.controls
|
|
|
|
.get_binding(GameInput::ToggleDebug)
|
|
|
|
{
|
|
|
|
Text::new(
|
|
|
|
&self
|
|
|
|
.voxygen_i18n
|
|
|
|
.get("hud.press_key_to_show_debug_info_fmt")
|
|
|
|
.replace("{key}", toggle_debug_key.to_string().as_str()),
|
|
|
|
)
|
|
|
|
.color(TEXT_COLOR)
|
|
|
|
.down_from(self.ids.help_info, 5.0)
|
|
|
|
.font_id(self.fonts.cyri.conrod_id)
|
|
|
|
.font_size(self.fonts.cyri.scale(12))
|
|
|
|
.set(self.ids.debug_info, ui_widgets);
|
|
|
|
}
|
2019-04-22 18:47:22 +00:00
|
|
|
}
|
2019-05-07 17:21:53 +00:00
|
|
|
|
2019-04-20 15:17:29 +00:00
|
|
|
// Help Text
|
2019-10-06 19:19:08 +00:00
|
|
|
if self.show.help && !self.show.map && !self.show.esc_menu {
|
|
|
|
Image::new(self.imgs.help)
|
|
|
|
.middle_of(ui_widgets.window)
|
2020-04-04 21:51:06 +00:00
|
|
|
.w_h(1260.0, 519.0)
|
2019-04-24 19:55:22 +00:00
|
|
|
.set(self.ids.help, ui_widgets);
|
2019-04-24 20:33:34 +00:00
|
|
|
// X-button
|
2019-04-28 16:44:44 +00:00
|
|
|
if Button::image(self.imgs.close_button)
|
2019-10-06 19:19:08 +00:00
|
|
|
.w_h(40.0, 40.0)
|
2019-04-28 16:44:44 +00:00
|
|
|
.hover_image(self.imgs.close_button_hover)
|
|
|
|
.press_image(self.imgs.close_button_press)
|
2019-10-06 19:19:08 +00:00
|
|
|
.top_right_with_margins_on(self.ids.help, 0.0, 0.0)
|
|
|
|
.color(Color::Rgba(1.0, 1.0, 1.0, 0.8))
|
2019-04-24 20:33:34 +00:00
|
|
|
.set(self.ids.button_help2, ui_widgets)
|
|
|
|
.was_clicked()
|
|
|
|
{
|
2019-05-04 17:24:26 +00:00
|
|
|
self.show.help = false;
|
2019-04-24 20:33:34 +00:00
|
|
|
};
|
2019-04-20 15:17:29 +00:00
|
|
|
}
|
|
|
|
|
2019-05-17 09:22:32 +00:00
|
|
|
// Bag button and nearby icons
|
2020-04-26 01:44:56 +00:00
|
|
|
let ecs = client.state().ecs();
|
|
|
|
let stats = ecs.read_storage::<comp::Stats>();
|
2020-05-14 23:10:27 +00:00
|
|
|
if let Some(player_stats) = stats.get(client.entity()) {
|
|
|
|
match Buttons::new(
|
|
|
|
client,
|
|
|
|
self.show.bag,
|
|
|
|
&self.imgs,
|
|
|
|
&self.fonts,
|
|
|
|
global_state,
|
|
|
|
&self.rot_imgs,
|
|
|
|
tooltip_manager,
|
|
|
|
&self.voxygen_i18n,
|
|
|
|
&player_stats,
|
|
|
|
)
|
|
|
|
.set(self.ids.buttons, ui_widgets)
|
|
|
|
{
|
|
|
|
Some(buttons::Event::ToggleBag) => self.show.toggle_bag(),
|
|
|
|
Some(buttons::Event::ToggleSettings) => self.show.toggle_settings(),
|
|
|
|
Some(buttons::Event::ToggleSocial) => self.show.toggle_social(),
|
|
|
|
Some(buttons::Event::ToggleSpell) => self.show.toggle_spell(),
|
|
|
|
Some(buttons::Event::ToggleMap) => self.show.toggle_map(),
|
2020-07-14 20:11:39 +00:00
|
|
|
Some(buttons::Event::ToggleCrafting) => self.show.toggle_crafting(),
|
2020-05-14 23:10:27 +00:00
|
|
|
None => {},
|
|
|
|
}
|
2019-05-04 10:43:37 +00:00
|
|
|
}
|
2019-04-26 13:13:30 +00:00
|
|
|
|
2020-06-02 02:42:26 +00:00
|
|
|
// Popup (waypoint saved and similar notifications)
|
2020-06-03 17:59:09 +00:00
|
|
|
Popup::new(
|
|
|
|
&self.voxygen_i18n,
|
|
|
|
client,
|
2020-06-02 02:42:26 +00:00
|
|
|
&self.new_notifications,
|
2020-06-03 17:59:09 +00:00
|
|
|
&self.fonts,
|
|
|
|
&self.show,
|
|
|
|
)
|
|
|
|
.set(self.ids.popup, ui_widgets);
|
2020-05-14 16:56:10 +00:00
|
|
|
|
2019-05-07 17:21:53 +00:00
|
|
|
// MiniMap
|
2019-12-30 12:16:35 +00:00
|
|
|
match MiniMap::new(
|
|
|
|
&self.show,
|
|
|
|
client,
|
|
|
|
&self.imgs,
|
2020-02-06 17:34:32 +00:00
|
|
|
&self.rot_imgs,
|
|
|
|
&self.world_map,
|
2019-12-30 12:16:35 +00:00
|
|
|
&self.fonts,
|
2020-07-10 14:00:20 +00:00
|
|
|
camera.get_orientation(),
|
2019-12-30 12:16:35 +00:00
|
|
|
)
|
|
|
|
.set(self.ids.minimap, ui_widgets)
|
2019-06-19 14:55:26 +00:00
|
|
|
{
|
2019-05-07 17:50:53 +00:00
|
|
|
Some(minimap::Event::Toggle) => self.show.toggle_mini_map(),
|
2020-02-01 20:39:39 +00:00
|
|
|
None => {},
|
2019-05-07 17:50:53 +00:00
|
|
|
}
|
2019-04-20 15:17:29 +00:00
|
|
|
|
|
|
|
// Bag contents
|
2019-05-04 17:24:26 +00:00
|
|
|
if self.show.bag {
|
2020-05-14 23:10:27 +00:00
|
|
|
if let Some(player_stats) = stats.get(client.entity()) {
|
|
|
|
match Bag::new(
|
|
|
|
client,
|
|
|
|
&self.imgs,
|
|
|
|
&self.item_imgs,
|
|
|
|
&self.fonts,
|
|
|
|
&self.rot_imgs,
|
|
|
|
tooltip_manager,
|
|
|
|
&mut self.slot_manager,
|
|
|
|
self.pulse,
|
|
|
|
&self.voxygen_i18n,
|
|
|
|
&player_stats,
|
|
|
|
&self.show,
|
|
|
|
)
|
|
|
|
.set(self.ids.bag, ui_widgets)
|
|
|
|
{
|
|
|
|
Some(bag::Event::Stats) => self.show.stats = !self.show.stats,
|
|
|
|
Some(bag::Event::Close) => {
|
|
|
|
self.show.bag(false);
|
|
|
|
self.force_ungrab = true;
|
|
|
|
},
|
|
|
|
None => {},
|
|
|
|
}
|
2019-03-22 03:55:42 +00:00
|
|
|
}
|
2019-04-26 16:13:30 +00:00
|
|
|
}
|
2019-05-07 17:21:53 +00:00
|
|
|
// Skillbar
|
2019-05-19 18:07:50 +00:00
|
|
|
// Get player stats
|
2020-01-12 16:43:25 +00:00
|
|
|
let ecs = client.state().ecs();
|
|
|
|
let entity = client.entity();
|
2020-03-14 21:33:20 +00:00
|
|
|
let stats = ecs.read_storage::<comp::Stats>();
|
|
|
|
let loadouts = ecs.read_storage::<comp::Loadout>();
|
|
|
|
let energies = ecs.read_storage::<comp::Energy>();
|
|
|
|
let character_states = ecs.read_storage::<comp::CharacterState>();
|
|
|
|
let controllers = ecs.read_storage::<comp::Controller>();
|
2020-04-11 06:33:06 +00:00
|
|
|
let inventories = ecs.read_storage::<comp::Inventory>();
|
|
|
|
if let (
|
|
|
|
Some(stats),
|
|
|
|
Some(loadout),
|
|
|
|
Some(energy),
|
|
|
|
Some(character_state),
|
|
|
|
Some(controller),
|
|
|
|
Some(inventory),
|
|
|
|
) = (
|
2020-01-17 22:00:00 +00:00
|
|
|
stats.get(entity),
|
2020-03-14 21:33:20 +00:00
|
|
|
loadouts.get(entity),
|
|
|
|
energies.get(entity),
|
|
|
|
character_states.get(entity),
|
|
|
|
controllers.get(entity).map(|c| &c.inputs),
|
2020-04-11 06:33:06 +00:00
|
|
|
inventories.get(entity),
|
2020-01-17 22:00:00 +00:00
|
|
|
) {
|
2020-01-12 16:43:25 +00:00
|
|
|
Skillbar::new(
|
|
|
|
global_state,
|
|
|
|
&self.imgs,
|
2020-04-11 06:33:06 +00:00
|
|
|
&self.item_imgs,
|
2020-01-12 16:43:25 +00:00
|
|
|
&self.fonts,
|
2020-04-12 01:20:48 +00:00
|
|
|
&self.rot_imgs,
|
2020-01-12 16:43:25 +00:00
|
|
|
&stats,
|
2020-03-14 21:33:20 +00:00
|
|
|
&loadout,
|
2020-01-12 16:43:25 +00:00
|
|
|
&energy,
|
2020-01-17 22:00:00 +00:00
|
|
|
&character_state,
|
2020-01-12 16:43:25 +00:00
|
|
|
self.pulse,
|
2020-01-18 01:10:12 +00:00
|
|
|
&controller,
|
2020-04-11 06:33:06 +00:00
|
|
|
&inventory,
|
|
|
|
&self.hotbar,
|
2020-04-12 01:20:48 +00:00
|
|
|
tooltip_manager,
|
2020-04-11 06:33:06 +00:00
|
|
|
&mut self.slot_manager,
|
2020-04-12 01:20:48 +00:00
|
|
|
&self.voxygen_i18n,
|
2020-06-03 17:59:09 +00:00
|
|
|
&self.show,
|
2020-01-12 16:43:25 +00:00
|
|
|
)
|
|
|
|
.set(self.ids.skillbar, ui_widgets);
|
2019-06-30 11:48:28 +00:00
|
|
|
}
|
2019-05-04 06:07:23 +00:00
|
|
|
|
2020-07-14 20:11:39 +00:00
|
|
|
// Crafting
|
|
|
|
if self.show.crafting {
|
|
|
|
if let Some(inventory) = inventories.get(entity) {
|
|
|
|
for event in Crafting::new(
|
|
|
|
//&self.show,
|
|
|
|
client,
|
|
|
|
&self.imgs,
|
|
|
|
&self.fonts,
|
|
|
|
&self.voxygen_i18n,
|
|
|
|
&self.rot_imgs,
|
|
|
|
tooltip_manager,
|
|
|
|
&self.item_imgs,
|
|
|
|
&inventory,
|
|
|
|
)
|
|
|
|
.set(self.ids.crafting_window, ui_widgets)
|
|
|
|
{
|
|
|
|
match event {
|
|
|
|
crafting::Event::CraftRecipe(r) => {
|
|
|
|
events.push(Event::CraftRecipe(r));
|
|
|
|
},
|
|
|
|
crafting::Event::Close => {
|
|
|
|
self.show.crafting(false);
|
|
|
|
self.force_ungrab = true;
|
|
|
|
},
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-06-04 07:11:35 +00:00
|
|
|
// Don't put NPC messages in chat box.
|
2020-06-11 05:16:42 +00:00
|
|
|
self.new_messages
|
|
|
|
.retain(|m| !matches!(m.chat_type, comp::ChatType::Npc(_, _)));
|
2020-06-04 07:11:35 +00:00
|
|
|
|
2019-05-03 16:56:18 +00:00
|
|
|
// Chat box
|
2019-10-23 19:40:45 +00:00
|
|
|
match Chat::new(
|
|
|
|
&mut self.new_messages,
|
2020-06-02 06:11:47 +00:00
|
|
|
&client,
|
2019-10-23 19:40:45 +00:00
|
|
|
global_state,
|
|
|
|
&self.imgs,
|
|
|
|
&self.fonts,
|
|
|
|
)
|
|
|
|
.and_then(self.force_chat_input.take(), |c, input| c.input(input))
|
2020-05-08 21:38:58 +00:00
|
|
|
.and_then(self.tab_complete.take(), |c, input| {
|
2020-06-02 06:11:47 +00:00
|
|
|
c.prepare_tab_completion(input)
|
2020-05-08 21:38:58 +00:00
|
|
|
})
|
2019-10-23 19:40:45 +00:00
|
|
|
.and_then(self.force_chat_cursor.take(), |c, pos| c.cursor_pos(pos))
|
|
|
|
.set(self.ids.chat, ui_widgets)
|
2019-09-02 04:54:44 +00:00
|
|
|
{
|
2020-05-08 21:38:58 +00:00
|
|
|
Some(chat::Event::TabCompletionStart(input)) => {
|
|
|
|
self.tab_complete = Some(input);
|
|
|
|
},
|
2019-05-03 16:56:18 +00:00
|
|
|
Some(chat::Event::SendMessage(message)) => {
|
|
|
|
events.push(Event::SendMessage(message));
|
2020-02-01 20:39:39 +00:00
|
|
|
},
|
2019-05-06 12:28:57 +00:00
|
|
|
Some(chat::Event::Focus(focus_id)) => {
|
|
|
|
self.to_focus = Some(Some(focus_id));
|
2020-02-01 20:39:39 +00:00
|
|
|
},
|
|
|
|
None => {},
|
2019-05-03 16:56:18 +00:00
|
|
|
}
|
2019-07-15 17:04:48 +00:00
|
|
|
|
2019-05-03 16:56:18 +00:00
|
|
|
self.new_messages = VecDeque::new();
|
2020-06-02 02:42:26 +00:00
|
|
|
self.new_notifications = VecDeque::new();
|
2019-05-03 16:56:18 +00:00
|
|
|
|
2019-05-17 09:22:32 +00:00
|
|
|
// Windows
|
2019-03-15 04:55:52 +00:00
|
|
|
|
2019-05-17 09:22:32 +00:00
|
|
|
// Char Window will always appear at the left side. Other Windows default to the
|
2020-02-01 20:39:39 +00:00
|
|
|
// left side, but when the Char Window is opened they will appear to the right
|
|
|
|
// of it.
|
2019-03-15 04:55:52 +00:00
|
|
|
|
2019-05-03 16:56:18 +00:00
|
|
|
// Settings
|
2019-05-04 17:24:26 +00:00
|
|
|
if let Windows::Settings = self.show.open_windows {
|
2020-01-17 23:43:18 +00:00
|
|
|
for event in SettingsWindow::new(
|
|
|
|
&global_state,
|
|
|
|
&self.show,
|
|
|
|
&self.imgs,
|
|
|
|
&self.fonts,
|
2020-01-26 19:29:46 +00:00
|
|
|
&self.voxygen_i18n,
|
2020-01-17 23:43:18 +00:00
|
|
|
)
|
|
|
|
.set(self.ids.settings_window, ui_widgets)
|
2019-03-15 04:55:52 +00:00
|
|
|
{
|
2019-05-18 23:55:06 +00:00
|
|
|
match event {
|
2020-05-25 01:29:47 +00:00
|
|
|
settings_window::Event::SpeechBubbleDarkMode(sbdm) => {
|
|
|
|
events.push(Event::SpeechBubbleDarkMode(sbdm));
|
|
|
|
},
|
2020-06-14 03:13:01 +00:00
|
|
|
settings_window::Event::SpeechBubbleIcon(sbi) => {
|
|
|
|
events.push(Event::SpeechBubbleIcon(sbi));
|
|
|
|
},
|
2020-01-10 00:33:38 +00:00
|
|
|
settings_window::Event::Sct(sct) => {
|
|
|
|
events.push(Event::Sct(sct));
|
2020-02-01 20:39:39 +00:00
|
|
|
},
|
2020-01-10 00:33:38 +00:00
|
|
|
settings_window::Event::SctPlayerBatch(sct_player_batch) => {
|
|
|
|
events.push(Event::SctPlayerBatch(sct_player_batch));
|
2020-02-01 20:39:39 +00:00
|
|
|
},
|
2020-01-10 00:33:38 +00:00
|
|
|
settings_window::Event::SctDamageBatch(sct_damage_batch) => {
|
|
|
|
events.push(Event::SctDamageBatch(sct_damage_batch));
|
2020-02-01 20:39:39 +00:00
|
|
|
},
|
2019-08-18 18:07:21 +00:00
|
|
|
settings_window::Event::ToggleHelp => self.show.help = !self.show.help,
|
2019-05-18 23:55:06 +00:00
|
|
|
settings_window::Event::ToggleDebug => self.show.debug = !self.show.debug,
|
2020-07-23 12:10:13 +00:00
|
|
|
settings_window::Event::ToggleTips(loading_tips) => {
|
|
|
|
events.push(Event::ToggleTips(loading_tips));
|
|
|
|
},
|
2019-06-02 02:17:36 +00:00
|
|
|
settings_window::Event::ChangeTab(tab) => self.show.open_setting_tab(tab),
|
2020-03-04 20:42:22 +00:00
|
|
|
settings_window::Event::Close => {
|
2020-07-15 23:19:11 +00:00
|
|
|
// Unpause the game if we are on singleplayer so that we can logout
|
2020-03-07 22:16:00 +00:00
|
|
|
#[cfg(feature = "singleplayer")]
|
2020-07-15 23:19:11 +00:00
|
|
|
global_state.unpause();
|
2020-03-04 20:42:22 +00:00
|
|
|
|
|
|
|
self.show.settings(false)
|
|
|
|
},
|
2019-06-05 15:57:48 +00:00
|
|
|
settings_window::Event::AdjustMousePan(sensitivity) => {
|
|
|
|
events.push(Event::AdjustMousePan(sensitivity));
|
2020-02-01 20:39:39 +00:00
|
|
|
},
|
2019-06-05 15:57:48 +00:00
|
|
|
settings_window::Event::AdjustMouseZoom(sensitivity) => {
|
|
|
|
events.push(Event::AdjustMouseZoom(sensitivity));
|
2020-02-01 20:39:39 +00:00
|
|
|
},
|
2019-10-23 19:40:45 +00:00
|
|
|
settings_window::Event::ChatTransp(chat_transp) => {
|
|
|
|
events.push(Event::ChatTransp(chat_transp));
|
2020-02-01 20:39:39 +00:00
|
|
|
},
|
2020-06-24 05:46:29 +00:00
|
|
|
settings_window::Event::ChatCharName(chat_char_name) => {
|
|
|
|
events.push(Event::ChatCharName(chat_char_name));
|
|
|
|
},
|
2019-10-02 13:09:05 +00:00
|
|
|
settings_window::Event::ToggleZoomInvert(zoom_inverted) => {
|
|
|
|
events.push(Event::ToggleZoomInvert(zoom_inverted));
|
2020-02-01 20:39:39 +00:00
|
|
|
},
|
2019-12-06 22:49:17 +00:00
|
|
|
settings_window::Event::ToggleMouseYInvert(mouse_y_inverted) => {
|
|
|
|
events.push(Event::ToggleMouseYInvert(mouse_y_inverted));
|
2020-02-01 20:39:39 +00:00
|
|
|
},
|
2020-04-23 22:59:34 +00:00
|
|
|
settings_window::Event::ToggleSmoothPan(smooth_pan_enabled) => {
|
|
|
|
events.push(Event::ToggleSmoothPan(smooth_pan_enabled));
|
|
|
|
},
|
2019-05-19 00:45:02 +00:00
|
|
|
settings_window::Event::AdjustViewDistance(view_distance) => {
|
|
|
|
events.push(Event::AdjustViewDistance(view_distance));
|
2020-02-01 20:39:39 +00:00
|
|
|
},
|
2020-04-25 13:04:30 +00:00
|
|
|
settings_window::Event::AdjustSpriteRenderDistance(view_distance) => {
|
|
|
|
events.push(Event::AdjustSpriteRenderDistance(view_distance));
|
|
|
|
},
|
2020-04-26 01:44:56 +00:00
|
|
|
settings_window::Event::AdjustFigureLoDRenderDistance(view_distance) => {
|
|
|
|
events.push(Event::AdjustFigureLoDRenderDistance(view_distance));
|
|
|
|
},
|
2019-07-07 00:15:22 +00:00
|
|
|
settings_window::Event::CrosshairTransp(crosshair_transp) => {
|
|
|
|
events.push(Event::CrosshairTransp(crosshair_transp));
|
2020-02-01 20:39:39 +00:00
|
|
|
},
|
2019-09-24 16:25:24 +00:00
|
|
|
settings_window::Event::AdjustMusicVolume(music_volume) => {
|
|
|
|
events.push(Event::AdjustMusicVolume(music_volume));
|
2020-02-01 20:39:39 +00:00
|
|
|
},
|
2019-09-24 16:25:24 +00:00
|
|
|
settings_window::Event::AdjustSfxVolume(sfx_volume) => {
|
|
|
|
events.push(Event::AdjustSfxVolume(sfx_volume));
|
2020-02-01 20:39:39 +00:00
|
|
|
},
|
2019-06-06 17:54:11 +00:00
|
|
|
settings_window::Event::MaximumFPS(max_fps) => {
|
2019-06-06 19:11:39 +00:00
|
|
|
events.push(Event::ChangeMaxFPS(max_fps));
|
2020-02-01 20:39:39 +00:00
|
|
|
},
|
2019-05-20 14:53:12 +00:00
|
|
|
settings_window::Event::ChangeAudioDevice(name) => {
|
|
|
|
events.push(Event::ChangeAudioDevice(name));
|
2020-02-01 20:39:39 +00:00
|
|
|
},
|
2019-07-23 01:02:57 +00:00
|
|
|
settings_window::Event::CrosshairType(crosshair_type) => {
|
|
|
|
events.push(Event::CrosshairType(crosshair_type));
|
2020-02-01 20:39:39 +00:00
|
|
|
},
|
2019-08-18 18:07:21 +00:00
|
|
|
settings_window::Event::ToggleXpBar(xp_bar) => {
|
|
|
|
events.push(Event::ToggleXpBar(xp_bar));
|
2020-02-01 20:39:39 +00:00
|
|
|
},
|
2019-08-18 18:07:21 +00:00
|
|
|
settings_window::Event::ToggleBarNumbers(bar_numbers) => {
|
|
|
|
events.push(Event::ToggleBarNumbers(bar_numbers));
|
2020-02-01 20:39:39 +00:00
|
|
|
},
|
2019-08-18 18:07:21 +00:00
|
|
|
settings_window::Event::ToggleShortcutNumbers(shortcut_numbers) => {
|
|
|
|
events.push(Event::ToggleShortcutNumbers(shortcut_numbers));
|
2020-02-01 20:39:39 +00:00
|
|
|
},
|
2019-07-26 02:28:53 +00:00
|
|
|
settings_window::Event::UiScale(scale_change) => {
|
|
|
|
events.push(Event::UiScale(scale_change));
|
2020-02-01 20:39:39 +00:00
|
|
|
},
|
2019-08-05 16:37:52 +00:00
|
|
|
settings_window::Event::AdjustFOV(new_fov) => {
|
|
|
|
events.push(Event::ChangeFOV(new_fov));
|
2020-02-01 20:39:39 +00:00
|
|
|
},
|
2020-02-12 13:55:26 +00:00
|
|
|
settings_window::Event::AdjustGamma(new_gamma) => {
|
|
|
|
events.push(Event::ChangeGamma(new_gamma));
|
|
|
|
},
|
2019-09-26 07:28:40 +00:00
|
|
|
settings_window::Event::ChangeAaMode(new_aa_mode) => {
|
|
|
|
events.push(Event::ChangeAaMode(new_aa_mode));
|
2020-02-01 20:39:39 +00:00
|
|
|
},
|
2020-01-19 03:58:25 +00:00
|
|
|
settings_window::Event::ChangeCloudMode(new_cloud_mode) => {
|
|
|
|
events.push(Event::ChangeCloudMode(new_cloud_mode));
|
2020-02-01 20:39:39 +00:00
|
|
|
},
|
2020-01-19 03:58:25 +00:00
|
|
|
settings_window::Event::ChangeFluidMode(new_fluid_mode) => {
|
|
|
|
events.push(Event::ChangeFluidMode(new_fluid_mode));
|
2020-02-01 20:39:39 +00:00
|
|
|
},
|
2020-01-17 23:43:18 +00:00
|
|
|
settings_window::Event::ChangeLanguage(language) => {
|
|
|
|
events.push(Event::ChangeLanguage(language));
|
2020-02-01 20:39:39 +00:00
|
|
|
},
|
2020-01-02 03:48:11 +00:00
|
|
|
settings_window::Event::ToggleFullscreen => {
|
|
|
|
events.push(Event::ToggleFullscreen);
|
2020-02-01 20:39:39 +00:00
|
|
|
},
|
2020-01-02 03:48:11 +00:00
|
|
|
settings_window::Event::AdjustWindowSize(new_size) => {
|
|
|
|
events.push(Event::AdjustWindowSize(new_size));
|
2020-02-01 20:39:39 +00:00
|
|
|
},
|
2020-04-08 17:36:37 +00:00
|
|
|
settings_window::Event::ChangeBinding(game_input) => {
|
|
|
|
events.push(Event::ChangeBinding(game_input));
|
|
|
|
},
|
2020-07-12 18:59:18 +00:00
|
|
|
settings_window::Event::ResetBindings => {
|
|
|
|
events.push(Event::ResetBindings);
|
|
|
|
},
|
2020-03-27 18:35:52 +00:00
|
|
|
settings_window::Event::ChangeFreeLookBehavior(behavior) => {
|
|
|
|
events.push(Event::ChangeFreeLookBehavior(behavior));
|
|
|
|
},
|
2020-06-06 18:09:01 +00:00
|
|
|
settings_window::Event::ChangeAutoWalkBehavior(behavior) => {
|
|
|
|
events.push(Event::ChangeAutoWalkBehavior(behavior));
|
|
|
|
},
|
|
|
|
settings_window::Event::ChangeStopAutoWalkOnInput(state) => {
|
|
|
|
events.push(Event::ChangeStopAutoWalkOnInput(state));
|
|
|
|
},
|
2019-05-07 17:50:53 +00:00
|
|
|
}
|
2019-03-15 04:55:52 +00:00
|
|
|
}
|
|
|
|
}
|
2019-04-24 20:33:34 +00:00
|
|
|
|
2019-08-07 13:14:26 +00:00
|
|
|
// Social Window
|
|
|
|
if self.show.social {
|
2020-07-27 03:37:09 +00:00
|
|
|
let ecs = client.state().ecs();
|
2020-08-02 23:53:02 +00:00
|
|
|
let _stats = ecs.read_storage::<comp::Stats>();
|
2020-07-27 03:37:09 +00:00
|
|
|
let me = client.entity();
|
2020-08-02 23:53:02 +00:00
|
|
|
if let Some(_stats) = stats.get(me) {
|
2020-07-27 03:37:09 +00:00
|
|
|
for event in Social::new(
|
|
|
|
&self.show,
|
|
|
|
client,
|
|
|
|
&self.imgs,
|
|
|
|
&self.fonts,
|
|
|
|
&self.voxygen_i18n,
|
2020-08-02 23:53:02 +00:00
|
|
|
//&stats,
|
2020-07-27 03:37:09 +00:00
|
|
|
info.selected_entity,
|
|
|
|
)
|
|
|
|
.set(self.ids.social_window, ui_widgets)
|
|
|
|
{
|
|
|
|
match event {
|
2020-08-02 23:53:02 +00:00
|
|
|
social::Event::Close => {
|
|
|
|
self.show.social(false);
|
|
|
|
self.force_ungrab = true;
|
|
|
|
},
|
2020-07-27 03:37:09 +00:00
|
|
|
social::Event::ChangeSocialTab(social_tab) => {
|
|
|
|
self.show.open_social_tab(social_tab)
|
|
|
|
},
|
|
|
|
social::Event::Invite(uid) => events.push(Event::InviteMember(uid)),
|
|
|
|
}
|
2020-07-12 00:39:50 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// Group Window
|
2020-07-25 23:21:15 +00:00
|
|
|
for event in Group::new(
|
|
|
|
&mut self.show,
|
|
|
|
client,
|
|
|
|
&global_state.settings,
|
|
|
|
&self.imgs,
|
|
|
|
&self.fonts,
|
|
|
|
&self.voxygen_i18n,
|
|
|
|
tooltip_manager,
|
|
|
|
&self.rot_imgs,
|
|
|
|
self.pulse,
|
|
|
|
&global_state,
|
|
|
|
)
|
|
|
|
.set(self.ids.group_window, ui_widgets)
|
|
|
|
{
|
|
|
|
match event {
|
|
|
|
group::Event::Accept => events.push(Event::AcceptInvite),
|
|
|
|
group::Event::Decline => events.push(Event::DeclineInvite),
|
|
|
|
group::Event::Kick(uid) => events.push(Event::KickMember(uid)),
|
|
|
|
group::Event::LeaveGroup => events.push(Event::LeaveGroup),
|
|
|
|
group::Event::AssignLeader(uid) => events.push(Event::AssignLeader(uid)),
|
2019-03-15 04:55:52 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-08-07 13:14:26 +00:00
|
|
|
// Spellbook
|
|
|
|
if self.show.spell {
|
2020-01-17 23:43:18 +00:00
|
|
|
match Spell::new(
|
|
|
|
&self.show,
|
|
|
|
client,
|
|
|
|
&self.imgs,
|
|
|
|
&self.fonts,
|
2020-01-26 19:29:46 +00:00
|
|
|
&self.voxygen_i18n,
|
2020-01-17 23:43:18 +00:00
|
|
|
)
|
|
|
|
.set(self.ids.spell, ui_widgets)
|
2019-08-07 13:14:26 +00:00
|
|
|
{
|
|
|
|
Some(spell::Event::Close) => {
|
|
|
|
self.show.spell(false);
|
|
|
|
self.force_ungrab = true;
|
2020-02-01 20:39:39 +00:00
|
|
|
},
|
|
|
|
None => {},
|
2019-04-28 04:44:13 +00:00
|
|
|
}
|
2019-03-15 04:55:52 +00:00
|
|
|
}
|
2019-04-30 20:43:55 +00:00
|
|
|
// Map
|
2019-05-04 17:24:26 +00:00
|
|
|
if self.show.map {
|
2020-07-01 19:05:44 +00:00
|
|
|
for event in Map::new(
|
2019-12-30 12:16:35 +00:00
|
|
|
&self.show,
|
|
|
|
client,
|
|
|
|
&self.imgs,
|
2020-02-06 17:34:32 +00:00
|
|
|
&self.rot_imgs,
|
|
|
|
&self.world_map,
|
2019-12-30 12:16:35 +00:00
|
|
|
&self.fonts,
|
|
|
|
self.pulse,
|
2020-03-27 03:05:04 +00:00
|
|
|
&self.voxygen_i18n,
|
2020-07-01 19:05:44 +00:00
|
|
|
&global_state,
|
2019-12-30 12:16:35 +00:00
|
|
|
)
|
|
|
|
.set(self.ids.map, ui_widgets)
|
2019-06-22 14:30:53 +00:00
|
|
|
{
|
2020-07-01 19:05:44 +00:00
|
|
|
match event {
|
|
|
|
map::Event::Close => {
|
|
|
|
self.show.map(false);
|
|
|
|
self.force_ungrab = true;
|
|
|
|
},
|
|
|
|
map::Event::MapZoom(map_zoom) => {
|
|
|
|
events.push(Event::MapZoom(map_zoom));
|
|
|
|
},
|
|
|
|
}
|
2019-03-15 04:55:52 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-05-04 17:24:26 +00:00
|
|
|
if self.show.esc_menu {
|
2020-01-26 19:29:46 +00:00
|
|
|
match EscMenu::new(&self.imgs, &self.fonts, &self.voxygen_i18n)
|
2020-01-17 23:43:18 +00:00
|
|
|
.set(self.ids.esc_menu, ui_widgets)
|
|
|
|
{
|
2019-06-02 02:17:36 +00:00
|
|
|
Some(esc_menu::Event::OpenSettings(tab)) => {
|
|
|
|
self.show.open_setting_tab(tab);
|
2020-02-01 20:39:39 +00:00
|
|
|
},
|
2019-05-25 12:59:25 +00:00
|
|
|
Some(esc_menu::Event::Close) => {
|
|
|
|
self.show.esc_menu = false;
|
2020-03-30 21:00:46 +00:00
|
|
|
self.show.want_grab = true;
|
|
|
|
self.force_ungrab = false;
|
2020-03-03 19:51:15 +00:00
|
|
|
|
|
|
|
// Unpause the game if we are on singleplayer
|
2020-07-15 23:19:11 +00:00
|
|
|
#[cfg(feature = "singleplayer")]
|
2020-03-07 22:16:00 +00:00
|
|
|
global_state.unpause();
|
2020-02-01 20:39:39 +00:00
|
|
|
},
|
2019-06-04 20:41:50 +00:00
|
|
|
Some(esc_menu::Event::Logout) => {
|
2020-03-03 22:07:49 +00:00
|
|
|
// Unpause the game if we are on singleplayer so that we can logout
|
2020-07-15 23:19:11 +00:00
|
|
|
#[cfg(feature = "singleplayer")]
|
2020-03-07 22:16:00 +00:00
|
|
|
global_state.unpause();
|
2020-03-03 22:07:49 +00:00
|
|
|
|
2019-06-04 20:41:50 +00:00
|
|
|
events.push(Event::Logout);
|
2020-02-01 20:39:39 +00:00
|
|
|
},
|
2019-05-03 16:56:18 +00:00
|
|
|
Some(esc_menu::Event::Quit) => events.push(Event::Quit),
|
2020-03-04 20:42:22 +00:00
|
|
|
Some(esc_menu::Event::CharacterSelection) => {
|
|
|
|
// Unpause the game if we are on singleplayer so that we can logout
|
2020-07-15 23:19:11 +00:00
|
|
|
#[cfg(feature = "singleplayer")]
|
2020-03-07 22:16:00 +00:00
|
|
|
global_state.unpause();
|
2020-03-04 20:42:22 +00:00
|
|
|
|
|
|
|
events.push(Event::CharacterSelection)
|
|
|
|
},
|
2020-02-01 20:39:39 +00:00
|
|
|
None => {},
|
2019-05-03 16:56:18 +00:00
|
|
|
}
|
|
|
|
}
|
2019-05-07 05:40:03 +00:00
|
|
|
|
2020-03-26 21:22:21 +00:00
|
|
|
// Free look indicator
|
|
|
|
if self.show.free_look {
|
|
|
|
Text::new(&self.voxygen_i18n.get("hud.free_look_indicator"))
|
|
|
|
.color(TEXT_BG)
|
|
|
|
.mid_top_with_margin_on(ui_widgets.window, 100.0)
|
|
|
|
.font_id(self.fonts.cyri.conrod_id)
|
|
|
|
.font_size(self.fonts.cyri.scale(20))
|
|
|
|
.set(self.ids.free_look_bg, ui_widgets);
|
|
|
|
Text::new(&self.voxygen_i18n.get("hud.free_look_indicator"))
|
|
|
|
.color(KILL_COLOR)
|
|
|
|
.top_left_with_margins_on(self.ids.free_look_bg, -1.0, -1.0)
|
|
|
|
.font_id(self.fonts.cyri.conrod_id)
|
|
|
|
.font_size(self.fonts.cyri.scale(20))
|
|
|
|
.set(self.ids.free_look_txt, ui_widgets);
|
|
|
|
}
|
|
|
|
|
2020-06-06 18:09:01 +00:00
|
|
|
// Auto walk indicator
|
|
|
|
if self.show.auto_walk {
|
|
|
|
Text::new(&self.voxygen_i18n.get("hud.auto_walk_indicator"))
|
|
|
|
.color(TEXT_BG)
|
|
|
|
.mid_top_with_margin_on(
|
|
|
|
ui_widgets.window,
|
|
|
|
if self.show.free_look { 128.0 } else { 100.0 },
|
|
|
|
)
|
|
|
|
.font_id(self.fonts.cyri.conrod_id)
|
|
|
|
.font_size(self.fonts.cyri.scale(20))
|
|
|
|
.set(self.ids.auto_walk_bg, ui_widgets);
|
|
|
|
Text::new(&self.voxygen_i18n.get("hud.auto_walk_indicator"))
|
|
|
|
.color(KILL_COLOR)
|
|
|
|
.top_left_with_margins_on(self.ids.auto_walk_bg, -1.0, -1.0)
|
|
|
|
.font_id(self.fonts.cyri.conrod_id)
|
|
|
|
.font_size(self.fonts.cyri.scale(20))
|
|
|
|
.set(self.ids.auto_walk_txt, ui_widgets);
|
|
|
|
}
|
|
|
|
|
2020-04-04 07:13:51 +00:00
|
|
|
// Maintain slot manager
|
|
|
|
for event in self.slot_manager.maintain(ui_widgets) {
|
2020-04-10 02:36:35 +00:00
|
|
|
use comp::slot::Slot;
|
2020-04-11 06:33:06 +00:00
|
|
|
use slots::SlotKind::*;
|
2020-04-10 02:36:35 +00:00
|
|
|
let to_slot = |slot_kind| match slot_kind {
|
2020-04-11 06:33:06 +00:00
|
|
|
Inventory(i) => Some(Slot::Inventory(i.0)),
|
|
|
|
Equip(e) => Some(Slot::Equip(e)),
|
|
|
|
Hotbar(_) => None,
|
2020-04-10 02:36:35 +00:00
|
|
|
};
|
2020-04-04 07:13:51 +00:00
|
|
|
match event {
|
2020-04-10 02:36:35 +00:00
|
|
|
slot::Event::Dragged(a, b) => {
|
|
|
|
// Swap between slots
|
|
|
|
if let (Some(a), Some(b)) = (to_slot(a), to_slot(b)) {
|
|
|
|
events.push(Event::SwapSlots(a, b));
|
2020-04-11 06:33:06 +00:00
|
|
|
} else if let (Inventory(i), Hotbar(h)) = (a, b) {
|
|
|
|
self.hotbar.add_inventory_link(h, i.0);
|
2020-06-16 13:55:37 +00:00
|
|
|
events.push(Event::ChangeHotbarState(self.hotbar.to_owned()));
|
2020-04-11 06:33:06 +00:00
|
|
|
} else if let (Hotbar(a), Hotbar(b)) = (a, b) {
|
|
|
|
self.hotbar.swap(a, b);
|
2020-06-16 13:55:37 +00:00
|
|
|
events.push(Event::ChangeHotbarState(self.hotbar.to_owned()));
|
2020-04-10 02:36:35 +00:00
|
|
|
}
|
2020-04-04 07:13:51 +00:00
|
|
|
},
|
2020-04-10 02:36:35 +00:00
|
|
|
slot::Event::Dropped(from) => {
|
|
|
|
// Drop item
|
|
|
|
if let Some(from) = to_slot(from) {
|
|
|
|
events.push(Event::DropSlot(from));
|
2020-04-11 06:33:06 +00:00
|
|
|
} else if let Hotbar(h) = from {
|
|
|
|
self.hotbar.clear_slot(h);
|
2020-06-16 13:55:37 +00:00
|
|
|
events.push(Event::ChangeHotbarState(self.hotbar.to_owned()));
|
2020-04-10 02:36:35 +00:00
|
|
|
}
|
2020-04-04 07:13:51 +00:00
|
|
|
},
|
2020-04-10 02:36:35 +00:00
|
|
|
slot::Event::Used(from) => {
|
|
|
|
// Item used (selected and then clicked again)
|
|
|
|
if let Some(from) = to_slot(from) {
|
|
|
|
events.push(Event::UseSlot(from));
|
2020-04-11 06:33:06 +00:00
|
|
|
} else if let Hotbar(h) = from {
|
|
|
|
self.hotbar.get(h).map(|s| {
|
|
|
|
match s {
|
|
|
|
hotbar::SlotContents::Inventory(i) => {
|
|
|
|
events.push(Event::UseSlot(comp::slot::Slot::Inventory(i)));
|
|
|
|
},
|
|
|
|
hotbar::SlotContents::Ability3 => {}, /* Event::Ability3(true),
|
|
|
|
* sticks */
|
|
|
|
}
|
|
|
|
});
|
2020-04-10 02:36:35 +00:00
|
|
|
}
|
2020-04-04 07:13:51 +00:00
|
|
|
},
|
|
|
|
}
|
|
|
|
}
|
2020-04-11 06:33:06 +00:00
|
|
|
self.hotbar.maintain_ability3(client);
|
2020-04-04 07:13:51 +00:00
|
|
|
|
2019-03-16 02:03:21 +00:00
|
|
|
events
|
2019-03-15 04:55:52 +00:00
|
|
|
}
|
|
|
|
|
2020-06-02 02:42:26 +00:00
|
|
|
pub fn new_message(&mut self, msg: comp::ChatMsg) { self.new_messages.push_back(msg); }
|
|
|
|
|
|
|
|
pub fn new_notification(&mut self, msg: common::msg::Notification) {
|
|
|
|
self.new_notifications.push_back(msg);
|
|
|
|
}
|
2019-03-17 05:26:51 +00:00
|
|
|
|
2019-07-26 02:28:53 +00:00
|
|
|
pub fn scale_change(&mut self, scale_change: ScaleChange) -> ScaleMode {
|
|
|
|
let scale_mode = match scale_change {
|
|
|
|
ScaleChange::Adjust(scale) => ScaleMode::Absolute(scale),
|
|
|
|
ScaleChange::ToAbsolute => self.ui.scale().scaling_mode_as_absolute(),
|
|
|
|
ScaleChange::ToRelative => self.ui.scale().scaling_mode_as_relative(),
|
|
|
|
};
|
|
|
|
self.ui.set_scaling_mode(scale_mode);
|
|
|
|
scale_mode
|
|
|
|
}
|
|
|
|
|
2019-05-17 09:22:32 +00:00
|
|
|
// Checks if a TextEdit widget has the keyboard captured.
|
2019-05-07 03:25:25 +00:00
|
|
|
fn typing(&self) -> bool {
|
|
|
|
if let Some(id) = self.ui.widget_capturing_keyboard() {
|
|
|
|
self.ui
|
|
|
|
.widget_graph()
|
|
|
|
.widget(id)
|
2019-05-14 06:43:07 +00:00
|
|
|
.filter(|c| {
|
|
|
|
c.type_id == std::any::TypeId::of::<<widget::TextEdit as Widget>::State>()
|
|
|
|
})
|
2019-05-07 03:25:25 +00:00
|
|
|
.is_some()
|
|
|
|
} else {
|
|
|
|
false
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-04-20 18:08:39 +00:00
|
|
|
pub fn handle_event(&mut self, event: WinEvent, global_state: &mut GlobalState) -> bool {
|
2020-04-11 06:33:06 +00:00
|
|
|
// Helper
|
|
|
|
fn handle_slot(
|
|
|
|
slot: hotbar::Slot,
|
|
|
|
state: bool,
|
|
|
|
events: &mut Vec<Event>,
|
|
|
|
slot_manager: &mut slots::SlotManager,
|
|
|
|
hotbar: &mut hotbar::State,
|
|
|
|
) {
|
|
|
|
if let Some(slots::SlotKind::Inventory(i)) = slot_manager.selected() {
|
|
|
|
hotbar.add_inventory_link(slot, i.0);
|
|
|
|
slot_manager.idle();
|
|
|
|
} else {
|
|
|
|
let just_pressed = hotbar.process_input(slot, state);
|
|
|
|
hotbar.get(slot).map(|s| match s {
|
|
|
|
hotbar::SlotContents::Inventory(i) => {
|
|
|
|
if just_pressed {
|
|
|
|
events.push(Event::UseSlot(comp::slot::Slot::Inventory(i)));
|
|
|
|
}
|
|
|
|
},
|
|
|
|
hotbar::SlotContents::Ability3 => events.push(Event::Ability3(state)),
|
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-04-20 18:08:39 +00:00
|
|
|
let cursor_grabbed = global_state.window.is_cursor_grabbed();
|
2019-05-07 20:00:03 +00:00
|
|
|
let handled = match event {
|
2019-03-22 03:55:42 +00:00
|
|
|
WinEvent::Ui(event) => {
|
2019-05-07 03:25:25 +00:00
|
|
|
if (self.typing() && event.is_keyboard() && self.show.ui)
|
2019-04-20 18:08:39 +00:00
|
|
|
|| !(cursor_grabbed && event.is_keyboard_or_mouse())
|
2019-04-01 20:31:29 +00:00
|
|
|
{
|
2019-03-22 03:55:42 +00:00
|
|
|
self.ui.handle_event(event);
|
|
|
|
}
|
|
|
|
true
|
2020-02-01 20:39:39 +00:00
|
|
|
},
|
2019-05-26 16:23:24 +00:00
|
|
|
WinEvent::InputUpdate(GameInput::ToggleInterface, true) if !self.typing() => {
|
2019-05-26 16:10:35 +00:00
|
|
|
self.show.toggle_ui();
|
|
|
|
true
|
2020-02-01 20:39:39 +00:00
|
|
|
},
|
2019-05-26 16:23:24 +00:00
|
|
|
WinEvent::InputUpdate(GameInput::ToggleCursor, true) if !self.typing() => {
|
2019-05-26 16:10:35 +00:00
|
|
|
self.force_ungrab = !self.force_ungrab;
|
|
|
|
true
|
2020-02-01 20:39:39 +00:00
|
|
|
},
|
2019-05-04 17:24:26 +00:00
|
|
|
_ if !self.show.ui => false,
|
2019-04-20 18:08:39 +00:00
|
|
|
WinEvent::Zoom(_) => !cursor_grabbed && !self.ui.no_widget_capturing_mouse(),
|
2019-05-25 14:39:27 +00:00
|
|
|
|
|
|
|
WinEvent::InputUpdate(GameInput::Enter, true) => {
|
2019-05-07 03:25:25 +00:00
|
|
|
self.ui.focus_widget(if self.typing() {
|
2019-05-06 12:28:57 +00:00
|
|
|
None
|
|
|
|
} else {
|
|
|
|
Some(self.ids.chat)
|
|
|
|
});
|
2019-03-30 02:15:27 +00:00
|
|
|
true
|
2020-02-01 20:39:39 +00:00
|
|
|
},
|
2019-05-25 14:39:27 +00:00
|
|
|
WinEvent::InputUpdate(GameInput::Escape, true) => {
|
2019-05-07 03:25:25 +00:00
|
|
|
if self.typing() {
|
2019-03-30 02:15:27 +00:00
|
|
|
self.ui.focus_widget(None);
|
|
|
|
} else {
|
2019-04-09 16:30:13 +00:00
|
|
|
// Close windows on esc
|
2020-03-01 22:18:22 +00:00
|
|
|
self.show.toggle_windows(global_state);
|
2019-03-30 02:15:27 +00:00
|
|
|
}
|
2019-04-09 16:30:13 +00:00
|
|
|
true
|
2020-02-01 20:39:39 +00:00
|
|
|
},
|
2019-05-25 14:39:27 +00:00
|
|
|
|
|
|
|
// Press key while not typing
|
2020-04-11 06:33:06 +00:00
|
|
|
WinEvent::InputUpdate(key, state) if !self.typing() => match key {
|
|
|
|
GameInput::Command if state => {
|
2019-07-05 16:21:11 +00:00
|
|
|
self.force_chat_input = Some("/".to_owned());
|
|
|
|
self.force_chat_cursor = Some(Index { line: 0, char: 1 });
|
|
|
|
self.ui.focus_widget(Some(self.ids.chat));
|
|
|
|
true
|
2020-02-01 20:39:39 +00:00
|
|
|
},
|
2020-04-11 06:33:06 +00:00
|
|
|
GameInput::Map if state => {
|
2019-05-04 17:24:26 +00:00
|
|
|
self.show.toggle_map();
|
2019-04-09 16:30:13 +00:00
|
|
|
true
|
2020-02-01 20:39:39 +00:00
|
|
|
},
|
2020-04-11 06:33:06 +00:00
|
|
|
GameInput::Bag if state => {
|
2019-05-04 17:24:26 +00:00
|
|
|
self.show.toggle_bag();
|
2019-04-09 16:30:13 +00:00
|
|
|
true
|
2020-02-01 20:39:39 +00:00
|
|
|
},
|
2020-04-11 06:33:06 +00:00
|
|
|
GameInput::Social if state => {
|
2019-08-07 13:14:26 +00:00
|
|
|
self.show.toggle_social();
|
2019-04-09 16:30:13 +00:00
|
|
|
true
|
2020-07-14 20:11:39 +00:00
|
|
|
},
|
|
|
|
GameInput::Crafting if state => {
|
|
|
|
self.show.toggle_crafting();
|
|
|
|
true
|
2020-02-01 20:39:39 +00:00
|
|
|
},
|
2020-04-11 06:33:06 +00:00
|
|
|
GameInput::Spellbook if state => {
|
2019-08-07 13:14:26 +00:00
|
|
|
self.show.toggle_spell();
|
2019-04-09 16:30:13 +00:00
|
|
|
true
|
2020-02-01 20:39:39 +00:00
|
|
|
},
|
2020-04-11 06:33:06 +00:00
|
|
|
GameInput::Settings if state => {
|
2019-05-04 17:24:26 +00:00
|
|
|
self.show.toggle_settings();
|
2019-04-09 16:30:13 +00:00
|
|
|
true
|
2020-02-01 20:39:39 +00:00
|
|
|
},
|
2020-04-11 06:33:06 +00:00
|
|
|
GameInput::Help if state => {
|
2019-05-04 17:24:26 +00:00
|
|
|
self.show.toggle_help();
|
2019-04-09 16:30:13 +00:00
|
|
|
true
|
2020-02-01 20:39:39 +00:00
|
|
|
},
|
2020-04-11 06:33:06 +00:00
|
|
|
GameInput::ToggleDebug if state => {
|
2020-01-10 00:33:38 +00:00
|
|
|
global_state.settings.gameplay.toggle_debug =
|
|
|
|
!global_state.settings.gameplay.toggle_debug;
|
2019-05-18 21:16:35 +00:00
|
|
|
true
|
2020-02-01 20:39:39 +00:00
|
|
|
},
|
2020-04-11 06:33:06 +00:00
|
|
|
GameInput::ToggleIngameUi if state => {
|
2019-05-21 04:55:20 +00:00
|
|
|
self.show.ingame = !self.show.ingame;
|
|
|
|
true
|
2020-02-01 20:39:39 +00:00
|
|
|
},
|
2020-04-11 06:33:06 +00:00
|
|
|
// Skillbar
|
|
|
|
GameInput::Slot1 => {
|
|
|
|
handle_slot(
|
|
|
|
hotbar::Slot::One,
|
|
|
|
state,
|
|
|
|
&mut self.events,
|
|
|
|
&mut self.slot_manager,
|
|
|
|
&mut self.hotbar,
|
|
|
|
);
|
|
|
|
true
|
|
|
|
},
|
|
|
|
GameInput::Slot2 => {
|
|
|
|
handle_slot(
|
|
|
|
hotbar::Slot::Two,
|
|
|
|
state,
|
|
|
|
&mut self.events,
|
|
|
|
&mut self.slot_manager,
|
|
|
|
&mut self.hotbar,
|
|
|
|
);
|
|
|
|
true
|
|
|
|
},
|
|
|
|
GameInput::Slot3 => {
|
|
|
|
handle_slot(
|
|
|
|
hotbar::Slot::Three,
|
|
|
|
state,
|
|
|
|
&mut self.events,
|
|
|
|
&mut self.slot_manager,
|
|
|
|
&mut self.hotbar,
|
|
|
|
);
|
|
|
|
true
|
|
|
|
},
|
|
|
|
GameInput::Slot4 => {
|
|
|
|
handle_slot(
|
|
|
|
hotbar::Slot::Four,
|
|
|
|
state,
|
|
|
|
&mut self.events,
|
|
|
|
&mut self.slot_manager,
|
|
|
|
&mut self.hotbar,
|
|
|
|
);
|
|
|
|
true
|
|
|
|
},
|
|
|
|
GameInput::Slot5 => {
|
|
|
|
handle_slot(
|
|
|
|
hotbar::Slot::Five,
|
|
|
|
state,
|
|
|
|
&mut self.events,
|
|
|
|
&mut self.slot_manager,
|
|
|
|
&mut self.hotbar,
|
|
|
|
);
|
|
|
|
true
|
|
|
|
},
|
|
|
|
GameInput::Slot6 => {
|
|
|
|
handle_slot(
|
|
|
|
hotbar::Slot::Six,
|
|
|
|
state,
|
|
|
|
&mut self.events,
|
|
|
|
&mut self.slot_manager,
|
|
|
|
&mut self.hotbar,
|
|
|
|
);
|
|
|
|
true
|
|
|
|
},
|
|
|
|
GameInput::Slot7 => {
|
|
|
|
handle_slot(
|
|
|
|
hotbar::Slot::Seven,
|
|
|
|
state,
|
|
|
|
&mut self.events,
|
|
|
|
&mut self.slot_manager,
|
|
|
|
&mut self.hotbar,
|
|
|
|
);
|
|
|
|
true
|
|
|
|
},
|
|
|
|
GameInput::Slot8 => {
|
|
|
|
handle_slot(
|
|
|
|
hotbar::Slot::Eight,
|
|
|
|
state,
|
|
|
|
&mut self.events,
|
|
|
|
&mut self.slot_manager,
|
|
|
|
&mut self.hotbar,
|
|
|
|
);
|
|
|
|
true
|
|
|
|
},
|
|
|
|
GameInput::Slot9 => {
|
|
|
|
handle_slot(
|
|
|
|
hotbar::Slot::Nine,
|
|
|
|
state,
|
|
|
|
&mut self.events,
|
|
|
|
&mut self.slot_manager,
|
|
|
|
&mut self.hotbar,
|
|
|
|
);
|
|
|
|
true
|
|
|
|
},
|
|
|
|
GameInput::Slot10 => {
|
|
|
|
handle_slot(
|
|
|
|
hotbar::Slot::Ten,
|
|
|
|
state,
|
|
|
|
&mut self.events,
|
|
|
|
&mut self.slot_manager,
|
|
|
|
&mut self.hotbar,
|
|
|
|
);
|
|
|
|
true
|
|
|
|
},
|
2019-04-09 16:30:13 +00:00
|
|
|
_ => false,
|
|
|
|
},
|
2019-05-25 14:39:27 +00:00
|
|
|
// Else the player is typing in chat
|
2019-06-06 14:48:41 +00:00
|
|
|
WinEvent::InputUpdate(_key, _) => self.typing(),
|
2019-05-07 03:25:25 +00:00
|
|
|
WinEvent::Char(_) => self.typing(),
|
2019-06-29 01:39:47 +00:00
|
|
|
WinEvent::Focused(state) => {
|
|
|
|
self.force_ungrab = !state;
|
|
|
|
true
|
2020-02-01 20:39:39 +00:00
|
|
|
},
|
2020-06-17 11:40:11 +00:00
|
|
|
WinEvent::Moved(_) => {
|
|
|
|
// Prevent the cursor from being grabbed while the window is being moved as this
|
|
|
|
// causes the window to move erratically
|
|
|
|
self.show.want_grab = false;
|
|
|
|
true
|
|
|
|
},
|
2019-05-25 14:39:27 +00:00
|
|
|
|
2019-03-22 03:55:42 +00:00
|
|
|
_ => false,
|
2019-05-07 20:00:03 +00:00
|
|
|
};
|
2019-05-17 09:22:32 +00:00
|
|
|
// Handle cursor grab.
|
2019-06-29 01:39:47 +00:00
|
|
|
global_state
|
|
|
|
.window
|
|
|
|
.grab_cursor(!self.force_ungrab && self.show.want_grab);
|
2019-05-08 20:15:58 +00:00
|
|
|
|
|
|
|
handled
|
2019-03-15 04:55:52 +00:00
|
|
|
}
|
|
|
|
|
2020-06-23 06:52:04 +00:00
|
|
|
#[allow(clippy::blocks_in_if_conditions)] // TODO: Pending review in #587
|
2019-05-23 08:18:25 +00:00
|
|
|
pub fn maintain(
|
|
|
|
&mut self,
|
2019-05-14 06:43:07 +00:00
|
|
|
client: &Client,
|
2019-05-23 08:18:25 +00:00
|
|
|
global_state: &mut GlobalState,
|
2019-05-23 09:30:00 +00:00
|
|
|
debug_info: DebugInfo,
|
2019-05-20 06:09:20 +00:00
|
|
|
camera: &Camera,
|
2019-12-30 12:16:35 +00:00
|
|
|
dt: Duration,
|
2020-05-18 22:40:28 +00:00
|
|
|
info: HudInfo,
|
2019-05-23 08:18:25 +00:00
|
|
|
) -> Vec<Event> {
|
2020-05-06 18:45:58 +00:00
|
|
|
// conrod eats tabs. Un-eat a tabstop so tab completion can work
|
|
|
|
if self.ui.ui.global_input().events().any(|event| {
|
|
|
|
use conrod_core::{event, input};
|
|
|
|
match event {
|
|
|
|
//event::Event::Raw(event::Input::Press(input::Button::Keyboard(input::Key::Tab)))
|
|
|
|
// => true,
|
|
|
|
event::Event::Ui(event::Ui::Press(
|
|
|
|
_,
|
|
|
|
event::Press {
|
|
|
|
button: event::Button::Keyboard(input::Key::Tab),
|
|
|
|
..
|
|
|
|
},
|
|
|
|
)) => true,
|
|
|
|
_ => false,
|
|
|
|
}
|
|
|
|
}) {
|
|
|
|
self.ui
|
|
|
|
.ui
|
|
|
|
.handle_event(conrod_core::event::Input::Text("\t".to_string()));
|
|
|
|
}
|
|
|
|
|
2019-05-06 12:28:57 +00:00
|
|
|
if let Some(maybe_id) = self.to_focus.take() {
|
|
|
|
self.ui.focus_widget(maybe_id);
|
|
|
|
}
|
2020-07-10 14:00:20 +00:00
|
|
|
let events = self.update_layout(client, global_state, debug_info, dt, info, camera);
|
2020-02-29 03:59:11 +00:00
|
|
|
let camera::Dependents {
|
|
|
|
view_mat, proj_mat, ..
|
|
|
|
} = camera.dependents();
|
|
|
|
self.ui.maintain(
|
|
|
|
&mut global_state.window.renderer_mut(),
|
|
|
|
Some(proj_mat * view_mat),
|
|
|
|
);
|
2019-10-09 19:28:05 +00:00
|
|
|
|
|
|
|
// Check if item images need to be reloaded
|
|
|
|
self.item_imgs.reload_if_changed(&mut self.ui);
|
|
|
|
|
2019-03-16 02:03:21 +00:00
|
|
|
events
|
2019-03-15 04:55:52 +00:00
|
|
|
}
|
|
|
|
|
2019-05-14 06:43:07 +00:00
|
|
|
pub fn render(&self, renderer: &mut Renderer, globals: &Consts<Globals>) {
|
2019-06-29 14:30:46 +00:00
|
|
|
// Don't show anything if the UI is toggled off.
|
|
|
|
if self.show.ui {
|
|
|
|
self.ui.render(renderer, Some(globals));
|
|
|
|
}
|
2019-03-15 04:55:52 +00:00
|
|
|
}
|
2020-03-26 21:22:21 +00:00
|
|
|
|
|
|
|
pub fn free_look(&mut self, free_look: bool) { self.show.free_look = free_look; }
|
2020-06-06 18:09:01 +00:00
|
|
|
|
|
|
|
pub fn auto_walk(&mut self, auto_walk: bool) { self.show.auto_walk = auto_walk; }
|
2019-03-15 04:55:52 +00:00
|
|
|
}
|