Merge branch 'master' of gitlab.com:veloren/veloren into sharp/jungle

This commit is contained in:
Joshua Yanovski 2019-08-19 11:04:09 +02:00
commit 50c90e1cde
77 changed files with 1245 additions and 335 deletions

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
assets/voxygen/element/buttons/checkbox/active.vox (Stored with Git LFS) Normal file

Binary file not shown.

BIN
assets/voxygen/element/buttons/checkbox/hover.vox (Stored with Git LFS) Normal file

Binary file not shown.

BIN
assets/voxygen/element/buttons/checkbox/inactive.vox (Stored with Git LFS) Normal file

Binary file not shown.

BIN
assets/voxygen/element/buttons/checkbox/inactive_hover.vox (Stored with Git LFS) Normal file

Binary file not shown.

BIN
assets/voxygen/element/buttons/checkbox/press.vox (Stored with Git LFS) Normal file

Binary file not shown.

BIN
assets/voxygen/element/icons/2hhammer_m1.vox (Stored with Git LFS) Normal file

Binary file not shown.

BIN
assets/voxygen/element/icons/2hhammer_m2.vox (Stored with Git LFS) Normal file

Binary file not shown.

BIN
assets/voxygen/element/icons/2hsword_m1.vox (Stored with Git LFS) Normal file

Binary file not shown.

BIN
assets/voxygen/element/icons/2hsword_m2.vox (Stored with Git LFS) Normal file

Binary file not shown.

BIN
assets/voxygen/element/icons/hammer_m1.vox (Stored with Git LFS) Normal file

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
assets/voxygen/element/misc_bg/level_down.vox (Stored with Git LFS) Normal file

Binary file not shown.

BIN
assets/voxygen/element/misc_bg/level_up.vox (Stored with Git LFS) Normal file

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
assets/voxygen/element/skill_bar/l.png (Stored with Git LFS)

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
assets/voxygen/element/skill_bar/r.png (Stored with Git LFS)

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
assets/voxygen/element/skillbar/bar_content.vox (Stored with Git LFS) Normal file

Binary file not shown.

BIN
assets/voxygen/element/skillbar/energybar_bg.vox (Stored with Git LFS) Normal file

Binary file not shown.

BIN
assets/voxygen/element/skillbar/healthbar_bg.vox (Stored with Git LFS) Normal file

Binary file not shown.

BIN
assets/voxygen/element/skillbar/skillbar_slot.vox (Stored with Git LFS) Normal file

Binary file not shown.

BIN
assets/voxygen/element/skillbar/skillbar_slot_bg.vox (Stored with Git LFS) Normal file

Binary file not shown.

BIN
assets/voxygen/element/skillbar/skillbar_slot_big.vox (Stored with Git LFS) Normal file

Binary file not shown.

BIN
assets/voxygen/element/skillbar/skillbar_slot_big_bg.vox (Stored with Git LFS) Normal file

Binary file not shown.

BIN
assets/voxygen/element/skillbar/skillbar_slot_l.vox (Stored with Git LFS) Normal file

Binary file not shown.

BIN
assets/voxygen/element/skillbar/skillbar_slot_r.vox (Stored with Git LFS) Normal file

Binary file not shown.

BIN
assets/voxygen/element/skillbar/xp_bar_content.vox (Stored with Git LFS) Normal file

Binary file not shown.

BIN
assets/voxygen/element/skillbar/xp_bar_left.vox (Stored with Git LFS) Normal file

Binary file not shown.

BIN
assets/voxygen/element/skillbar/xp_bar_mid.vox (Stored with Git LFS) Normal file

Binary file not shown.

BIN
assets/voxygen/element/skillbar/xp_bar_right.vox (Stored with Git LFS) Normal file

Binary file not shown.

Binary file not shown.

View File

@ -12,6 +12,12 @@ pub enum HealthSource {
LevelUp,
Unknown,
}
#[derive(Clone, Copy, Debug, Serialize, Deserialize)]
pub enum EnergySource {
CastSpell,
LevelUp,
Unknown,
}
#[derive(Clone, Copy, Debug, Serialize, Deserialize)]
pub struct Health {
@ -20,6 +26,13 @@ pub struct Health {
pub last_change: Option<(i32, f64, HealthSource)>,
}
#[derive(Clone, Copy, Debug, Serialize, Deserialize)]
pub struct Energy {
current: u32,
maximum: u32,
pub last_change: Option<(i32, f64, EnergySource)>,
}
#[derive(Clone, Copy, Debug, Serialize, Deserialize)]
pub struct Exp {
current: f64,
@ -57,6 +70,32 @@ impl Health {
}
}
impl Energy {
pub fn current(&self) -> u32 {
self.current
}
pub fn maximum(&self) -> u32 {
self.maximum
}
pub fn set_to(&mut self, amount: u32, cause: EnergySource) {
let amount = amount.min(self.maximum);
self.last_change = Some((amount as i32 - self.current as i32, 0.0, cause));
self.current = amount;
}
pub fn change_by(&mut self, amount: i32, cause: EnergySource) {
self.current = ((self.current as i32 + amount).max(0) as u32).min(self.maximum);
self.last_change = Some((amount, 0.0, cause));
}
pub fn set_maximum(&mut self, amount: u32) {
self.maximum = amount;
self.current = self.current.min(self.maximum);
}
}
impl Exp {
pub fn current(&self) -> f64 {
self.current
@ -103,6 +142,7 @@ impl Level {
pub struct Stats {
pub name: String,
pub health: Health,
pub energy: Energy,
pub level: Level,
pub exp: Exp,
pub is_dead: bool,
@ -134,6 +174,11 @@ impl Stats {
current: 0.0,
maximum: 50.0,
},
energy: Energy {
current: 200,
maximum: 200,
last_change: None,
},
is_dead: false,
}
}
@ -143,6 +188,12 @@ impl Stats {
self.health.current = amount;
self
}
pub fn with_max_energy(mut self, amount: u32) -> Self {
self.energy.maximum = amount;
self.energy.current = amount;
self
}
}
impl Component for Stats {

View File

@ -61,7 +61,9 @@ impl ChatCommand {
if !server.entity_is_admin(entity) {
server.clients.notify(
entity,
ServerMsg::private(String::from("You have no permission to do that.")),
ServerMsg::private(String::from(
"Unavailable command '/{}'.\nType '/help' for available commands",
)),
);
return;
} else {
@ -211,7 +213,7 @@ fn handle_jump(server: &mut Server, entity: EcsEntity, args: String, action: &Ch
}
None => server.clients.notify(
entity,
ServerMsg::private(String::from("You have no position!")),
ServerMsg::private(String::from("You have no position.")),
),
}
}
@ -231,7 +233,7 @@ fn handle_goto(server: &mut Server, entity: EcsEntity, args: String, action: &Ch
} else {
server.clients.notify(
entity,
ServerMsg::private(String::from("You don't have a position!")),
ServerMsg::private(String::from("You have no position.")),
);
}
} else {
@ -279,7 +281,7 @@ fn handle_time(server: &mut Server, entity: EcsEntity, args: String, action: &Ch
0,
);
let msg = match current_time {
Some(time) => format!("Current time is: {}", time.format("%H:%M").to_string()),
Some(time) => format!("It is {}", time.format("%H:%M").to_string()),
None => String::from("Unknown Time"),
};
server.clients.notify(entity, ServerMsg::private(msg));

View File

@ -1167,7 +1167,7 @@ impl Server {
self.clients.notify(
entity,
ServerMsg::private(format!(
"Unrecognised command: '/{}'\ntype '/help' for a list of available commands",
"Unknown command '/{}'.\nType '/help' for available commands",
kwd
)),
);

View File

@ -24,7 +24,7 @@ impl Default for ServerSettings {
server_description: "This is the best Veloren server.".to_owned(),
max_players: 100,
start_time: 9.0 * 3600.0,
admins: vec![],
admins: vec!["Pfau".to_owned()],
}
}
}
@ -66,7 +66,7 @@ impl ServerSettings {
address: SocketAddr::from(([0; 4], 14004)),
world_seed: 1337,
server_name: "Singleplayer".to_owned(),
server_description: "The main feature is loneliness!".to_owned(),
server_description: "Who needs friends anyway?".to_owned(),
max_players: 100,
start_time: 9.0 * 3600.0,
admins: vec!["singleplayer".to_string()], // TODO: Let the player choose if they want to use admin commands or not

View File

@ -13,6 +13,22 @@ image_ids! {
bag_mid: "voxygen.element.bag.mid",
bag_bot: "voxygen.element.bag.bot",
// Skillbar
xp_bar_mid: "voxygen.element.skillbar.xp_bar_mid",
xp_bar_left: "voxygen.element.skillbar.xp_bar_left",
xp_bar_right: "voxygen.element.skillbar.xp_bar_right",
skillbar_slot: "voxygen.element.skillbar.skillbar_slot",
skillbar_slot_l: "voxygen.element.skillbar.skillbar_slot_l",
skillbar_slot_r: "voxygen.element.skillbar.skillbar_slot_r",
skillbar_slot_bg: "voxygen.element.skillbar.skillbar_slot_bg",
skillbar_slot_big: "voxygen.element.skillbar.skillbar_slot_big",
skillbar_slot_big_bg: "voxygen.element.skillbar.skillbar_slot_big_bg",
healthbar_bg: "voxygen.element.skillbar.healthbar_bg",
energybar_bg: "voxygen.element.skillbar.energybar_bg",
bar_content: "voxygen.element.skillbar.bar_content",
level_up: "voxygen.element.misc_bg.level_up",
level_down:"voxygen.element.misc_bg.level_down",
// Window Parts
window_3: "voxygen.element.frames.window_3",
tab_bg: "voxygen.element.frames.tab_bg",
@ -41,11 +57,6 @@ image_ids! {
settings_button_pressed: "voxygen.element.buttons.settings_button_pressed",
settings_button_hover: "voxygen.element.buttons.settings_button_hover",
settings_button_press: "voxygen.element.buttons.settings_button_press",
check: "voxygen.element.buttons.check.no",
check_mo: "voxygen.element.buttons.check.no_mo",
check_press: "voxygen.element.buttons.check.press",
check_checked: "voxygen.element.buttons.check.yes",
check_checked_mo: "voxygen.element.buttons.check.yes_mo",
slider: "voxygen.element.slider.track",
slider_indicator: "voxygen.element.slider.indicator",
esc_frame: "voxygen.element.frames.esc_menu",
@ -64,6 +75,12 @@ image_ids! {
// Crosshair
crosshair_inner: "voxygen.element.misc_bg.crosshair_inner",
// Icons
twohsword_m1: "voxygen.element.icons.2hsword_m1",
twohsword_m2: "voxygen.element.icons.2hsword_m2",
twohhammer_m1: "voxygen.element.icons.2hhammer_m1",
twohhammer_m2: "voxygen.element.icons.2hhammer_m2",
////////////////////////////////////////////////////////////////////////
<VoxelMs9Graphic>
@ -76,6 +93,19 @@ image_ids! {
crosshair_bg_press: "voxygen.element.misc_bg.crosshair_bg_press",
crosshair_bg_pressed: "voxygen.element.misc_bg.crosshair_bg_pressed",
// Checkboxes and Radio buttons
check: "voxygen.element.buttons.radio.inactive",
check_mo: "voxygen.element.buttons.radio.inactive_hover",
check_press: "voxygen.element.buttons.radio.press",
check_checked: "voxygen.element.buttons.radio.active",
check_checked_mo: "voxygen.element.buttons.radio.hover",
checkbox: "voxygen.element.buttons.checkbox.inactive",
checkbox_mo: "voxygen.element.buttons.checkbox.inactive_hover",
checkbox_press: "voxygen.element.buttons.checkbox.press",
checkbox_checked: "voxygen.element.buttons.checkbox.active",
checkbox_checked_mo: "voxygen.element.buttons.checkbox.hover",
// Buttons
mmap_closed: "voxygen.element.buttons.button_mmap_closed",
mmap_closed_hover: "voxygen.element.buttons.button_mmap_closed_hover",
@ -150,6 +180,7 @@ image_ids! {
key: "voxygen.voxel.object.key",
key_gold: "voxygen.voxel.object.key_gold",
//////////////////////////////////////////////////////////////////////////////////////////////////////
<ImageGraphic>
@ -173,15 +204,6 @@ image_ids! {
grid_button_press: "voxygen.element.buttons.border_press",
grid_button_open: "voxygen.element.buttons.border_pressed",
// Skillbar Module
sb_grid: "voxygen.element.skill_bar.sbar_grid",
sb_grid_bg: "voxygen.element.skill_bar.sbar_grid_bg",
l_click: "voxygen.element.skill_bar.l",
r_click: "voxygen.element.skill_bar.r",
mana_bar: "voxygen.element.skill_bar.mana_bar",
health_bar: "voxygen.element.skill_bar.health_bar",
xp_bar: "voxygen.element.skill_bar.xp_bar",
esc_bg: "voxygen.element.frames.menu",
window_frame_2: "voxygen.element.frames.window_2",

View File

@ -1,10 +1,12 @@
use conrod_core::{
color,
widget::{self, Button, Image, Rectangle, Text},
widget_ids, Colorable, Positionable, Sizeable, Widget, WidgetCommon,
widget_ids, Color, Colorable, Positionable, Sizeable, Widget, WidgetCommon,
};
use super::{img_ids::Imgs, Fonts, Show, TEXT_COLOR};
use std::time::{Duration, Instant};
use super::{img_ids::Imgs, Fonts, Show, HP_COLOR, TEXT_COLOR};
use client::{self, Client};
widget_ids! {
@ -13,6 +15,7 @@ widget_ids! {
mmap_frame_bg,
mmap_location,
mmap_button,
zone_display,
}
}
@ -42,6 +45,9 @@ impl<'a> MiniMap<'a> {
pub struct State {
ids: Ids,
last_region_name: Option<String>,
last_update: Instant,
}
pub enum Event {
@ -56,6 +62,9 @@ impl<'a> Widget for MiniMap<'a> {
fn init_state(&self, id_gen: widget::id::Generator) -> Self::State {
State {
ids: Ids::new(id_gen),
last_region_name: None,
last_update: Instant::now(),
}
}
@ -105,6 +114,53 @@ impl<'a> Widget for MiniMap<'a> {
return Some(Event::Toggle);
}
// Display zone name on entry
const FADE_IN: f32 = 0.5;
const FADE_HOLD: f32 = 1.0;
const FADE_OUT: f32 = 3.0;
match self.client.current_chunk() {
Some(chunk) => {
let current = chunk.meta().name();
// Check if no other popup is displayed and a new one is needed
if state.last_update.elapsed()
> Duration::from_secs_f32(FADE_IN + FADE_HOLD + FADE_OUT)
&& state
.last_region_name
.as_ref()
.map(|l| l != current)
.unwrap_or(true)
{
// Update last_region
state.update(|s| s.last_region_name = Some(current.to_owned()));
state.update(|s| s.last_update = Instant::now());
}
let seconds = state.last_update.elapsed().as_secs_f32();
let fade = if seconds < FADE_IN {
seconds / FADE_IN
} else if seconds < FADE_IN + FADE_HOLD {
1.0
} else {
(1.0 - (seconds - FADE_IN - FADE_HOLD) / FADE_OUT).max(0.0)
};
// Region Name
Text::new(state.last_region_name.as_ref().unwrap_or(&"".to_owned()))
.mid_top_with_margin_on(ui.window, 200.0)
.font_size(80)
.color(Color::Rgba(1.0, 1.0, 1.0, fade))
.set(state.ids.zone_display, ui);
}
None => Text::new(" ")
.middle_of(ui.window)
.font_size(14)
.color(HP_COLOR)
.set(state.ids.zone_display, ui),
}
// TODO: Subregion name display
// Title
match self.client.current_chunk() {
Some(chunk) => Text::new(chunk.meta().name())

View File

@ -55,8 +55,13 @@ const XP_COLOR: Color = Color::Rgba(0.59, 0.41, 0.67, 1.0);
const TEXT_COLOR: Color = Color::Rgba(1.0, 1.0, 1.0, 1.0);
const TEXT_COLOR_2: Color = Color::Rgba(0.0, 0.0, 0.0, 1.0);
const TEXT_COLOR_3: Color = Color::Rgba(1.0, 1.0, 1.0, 0.1);
//const BG_COLOR: Color = Color::Rgba(1.0, 1.0, 1.0, 0.8);
const HP_COLOR: Color = Color::Rgba(0.33, 0.63, 0.0, 1.0);
const MANA_COLOR: Color = Color::Rgba(0.42, 0.41, 0.66, 1.0);
const LOW_HP_COLOR: Color = Color::Rgba(0.93, 0.59, 0.03, 1.0);
const CRITICAL_HP_COLOR: Color = Color::Rgba(1.0, 0.0, 0.0, 1.0);
const MANA_COLOR: Color = Color::Rgba(0.47, 0.55, 1.0, 0.9);
//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);
const META_COLOR: Color = Color::Rgba(1.0, 1.0, 0.0, 1.0);
const TELL_COLOR: Color = Color::Rgba(0.98, 0.71, 1.0, 1.0);
const PRIVATE_COLOR: Color = Color::Rgba(1.0, 1.0, 0.0, 1.0); // Difference between private and tell?
@ -151,6 +156,10 @@ pub enum Event {
ChangeFOV(u16),
CrosshairTransp(f32),
CrosshairType(CrosshairType),
ToggleXpBar(XpBar),
ToggleEnBars(EnBars),
ToggleBarNumbers(BarNumbers),
ToggleShortcutNumbers(ShortcutNumbers),
UiScale(ScaleChange),
CharacterSelection,
SwapInventorySlots(usize, usize),
@ -174,6 +183,28 @@ pub enum CrosshairType {
RoundEdges,
Edges,
}
#[derive(Clone, Copy, Debug, Serialize, Deserialize)]
pub enum XpBar {
Always,
OnGain,
}
#[derive(Clone, Copy, Debug, Serialize, Deserialize)]
pub enum EnBars {
Always,
OnLoss,
}
#[derive(Clone, Copy, Debug, Serialize, Deserialize)]
pub enum BarNumbers {
Values,
Percent,
Off,
}
#[derive(Clone, Copy, Debug, Serialize, Deserialize)]
pub enum ShortcutNumbers {
On,
Off,
}
pub struct Show {
ui: bool,
@ -686,7 +717,8 @@ impl Hud {
.read_storage::<comp::Stats>()
.get(client.entity())
{
Skillbar::new(&self.imgs, &self.fonts, stats).set(self.ids.skillbar, ui_widgets);
Skillbar::new(global_state, &self.imgs, &self.fonts, stats)
.set(self.ids.skillbar, ui_widgets);
}
// Chat box
@ -722,10 +754,7 @@ impl Hud {
.set(self.ids.settings_window, ui_widgets)
{
match event {
settings_window::Event::ToggleHelp => self.show.toggle_help(),
settings_window::Event::ToggleInventoryTestButton => {
self.show.inventory_test_button = !self.show.inventory_test_button
}
settings_window::Event::ToggleHelp => self.show.help = !self.show.help,
settings_window::Event::ToggleDebug => self.show.debug = !self.show.debug,
settings_window::Event::ChangeTab(tab) => self.show.open_setting_tab(tab),
settings_window::Event::Close => self.show.settings(false),
@ -753,6 +782,18 @@ impl Hud {
settings_window::Event::CrosshairType(crosshair_type) => {
events.push(Event::CrosshairType(crosshair_type));
}
settings_window::Event::ToggleXpBar(xp_bar) => {
events.push(Event::ToggleXpBar(xp_bar));
}
settings_window::Event::ToggleEnBars(en_bars) => {
events.push(Event::ToggleEnBars(en_bars));
}
settings_window::Event::ToggleBarNumbers(bar_numbers) => {
events.push(Event::ToggleBarNumbers(bar_numbers));
}
settings_window::Event::ToggleShortcutNumbers(shortcut_numbers) => {
events.push(Event::ToggleShortcutNumbers(shortcut_numbers));
}
settings_window::Event::UiScale(scale_change) => {
events.push(Event::UiScale(scale_change));
}

View File

@ -1,4 +1,7 @@
use super::{img_ids::Imgs, CrosshairType, Fonts, Show, TEXT_COLOR};
use super::{
img_ids::Imgs, BarNumbers, CrosshairType, EnBars, Fonts, ShortcutNumbers, Show, XpBar,
TEXT_COLOR,
};
use crate::{
audio::base::Genre,
ui::{ImageSlider, ScaleMode, ToggleButton},
@ -42,8 +45,6 @@ widget_ids! {
debug_button,
debug_button_label,
interface,
inventory_test_button,
inventory_test_button_label,
mouse_pan_slider,
mouse_pan_label,
mouse_pan_value,
@ -81,6 +82,21 @@ widget_ids! {
audio_volume_text,
audio_device_list,
audio_device_text,
hotbar_title,
bar_numbers_title,
show_bar_numbers_none_button,
show_bar_numbers_none_text,
show_bar_numbers_values_button,
show_bar_numbers_values_text,
show_bar_numbers_percentage_button,
show_bar_numbers_percentage_text,
show_shortcuts_button,
show_shortcuts_text,
show_xpbar_button,
show_xpbar_text,
show_bars_button,
show_bars_text,
placeholder,
}
}
@ -100,7 +116,6 @@ pub struct SettingsWindow<'a> {
imgs: &'a Imgs,
fonts: &'a Fonts,
#[conrod(common_builder)]
common: widget::CommonBuilder,
}
@ -128,8 +143,11 @@ pub struct State {
pub enum Event {
ToggleHelp,
ToggleInventoryTestButton,
ToggleDebug,
ToggleXpBar(XpBar),
ToggleEnBars(EnBars),
ToggleBarNumbers(BarNumbers),
ToggleShortcutNumbers(ShortcutNumbers),
ChangeTab(SettingsTab),
Close,
AdjustMousePan(u32),
@ -169,6 +187,9 @@ impl<'a> Widget for SettingsWindow<'a> {
let widget::UpdateArgs { state, ui, .. } = args;
let mut events = Vec::new();
let bar_values = self.global_state.settings.gameplay.bar_numbers;
//let mut xp_bar = self.global_state.settings.gameplay.xp_bar;
// Frame Alignment
Rectangle::fill_with([824.0, 488.0], color::TRANSPARENT)
@ -254,19 +275,22 @@ impl<'a> Widget for SettingsWindow<'a> {
.set(state.ids.general_txt, ui);
// Help
let show_help =
ToggleButton::new(self.show.help, self.imgs.check, self.imgs.check_checked)
.w_h(288.0 / 24.0, 288.0 / 24.0)
let show_help = ToggleButton::new(
self.show.help,
self.imgs.checkbox,
self.imgs.checkbox_checked,
)
.w_h(18.0, 18.0)
.down_from(state.ids.general_txt, 20.0)
.hover_images(self.imgs.check_checked_mo, self.imgs.check_mo)
.press_images(self.imgs.check_press, self.imgs.check_press)
.hover_images(self.imgs.checkbox_mo, self.imgs.checkbox_checked_mo)
.press_images(self.imgs.checkbox_press, self.imgs.checkbox_checked)
.set(state.ids.button_help, ui);
if self.show.help != show_help {
events.push(Event::ToggleHelp);
}
Text::new("Show Help")
Text::new("Show Help Window")
.right_from(state.ids.button_help, 10.0)
.font_size(14)
.font_id(self.fonts.opensans)
@ -274,44 +298,23 @@ impl<'a> Widget for SettingsWindow<'a> {
.color(TEXT_COLOR)
.set(state.ids.show_help_label, ui);
// Inventory test
let inventory_test_button = ToggleButton::new(
self.show.inventory_test_button,
self.imgs.check,
self.imgs.check_checked,
)
.w_h(288.0 / 24.0, 288.0 / 24.0)
.down_from(state.ids.button_help, 7.0)
.hover_images(self.imgs.check_checked_mo, self.imgs.check_mo)
.press_images(self.imgs.check_press, self.imgs.check_press)
.set(state.ids.inventory_test_button, ui);
if self.show.inventory_test_button != inventory_test_button {
events.push(Event::ToggleInventoryTestButton);
}
Text::new("Show Inventory Test Button")
.right_from(state.ids.inventory_test_button, 10.0)
.font_size(14)
.font_id(self.fonts.opensans)
.graphics_for(state.ids.inventory_test_button)
.color(TEXT_COLOR)
.set(state.ids.inventory_test_button_label, ui);
// Debug
let show_debug =
ToggleButton::new(self.show.debug, self.imgs.check, self.imgs.check_checked)
.w_h(288.0 / 24.0, 288.0 / 24.0)
.down_from(state.ids.inventory_test_button, 7.0)
.hover_images(self.imgs.check_checked_mo, self.imgs.check_mo)
.press_images(self.imgs.check_press, self.imgs.check_press)
let show_debug = ToggleButton::new(
self.show.debug,
self.imgs.checkbox,
self.imgs.checkbox_checked,
)
.w_h(18.0, 18.0)
.down_from(state.ids.button_help, 8.0)
.hover_images(self.imgs.checkbox_mo, self.imgs.checkbox_checked_mo)
.press_images(self.imgs.checkbox_press, self.imgs.checkbox_checked)
.set(state.ids.debug_button, ui);
if self.show.debug != show_debug {
events.push(Event::ToggleDebug);
}
Text::new("Show Debug Window")
Text::new("Show Debug Info")
.right_from(state.ids.debug_button, 10.0)
.font_size(14)
.font_id(self.fonts.opensans)
@ -331,7 +334,7 @@ impl<'a> Widget for SettingsWindow<'a> {
let (check_img, check_mo_img, check_press_img, relative_selected) = match ui_scale {
ScaleMode::RelativeToWindow(_) => (
self.imgs.check_checked,
self.imgs.check_checked,
self.imgs.check_checked_mo,
self.imgs.check_checked,
true,
),
@ -366,7 +369,7 @@ impl<'a> Widget for SettingsWindow<'a> {
let (check_img, check_mo_img, check_press_img, absolute_selected) = match ui_scale {
ScaleMode::Absolute(_) => (
self.imgs.check_checked,
self.imgs.check_checked,
self.imgs.check_checked_mo,
self.imgs.check_checked,
true,
),
@ -379,7 +382,7 @@ impl<'a> Widget for SettingsWindow<'a> {
};
if Button::image(check_img)
.w_h(288.0 / 24.0, 288.0 / 24.0)
.down_from(state.ids.relative_to_win_button, 20.0)
.down_from(state.ids.relative_to_win_button, 8.0)
.hover_image(check_mo_img)
.press_image(check_press_img)
.set(state.ids.absolute_scale_button, ui)
@ -415,13 +418,15 @@ impl<'a> Widget for SettingsWindow<'a> {
{
events.push(Event::UiScale(ScaleChange::Adjust(2.0f64.powf(new_val))));
}
// Custom Scaling Text
Text::new(&format!("{:.2}", scale))
.up_from(state.ids.ch_transp_value, 75.0)
.right_from(state.ids.ui_scale_slider, 10.0)
.font_size(14)
.font_id(self.fonts.opensans)
.color(TEXT_COLOR)
.set(state.ids.ui_scale_value, ui);
} else {
// Grey and unfunctional slider when Relative is selected
ImageSlider::continuous(0.0, 0.0, 1.0, self.imgs.nothing, self.imgs.slider)
.w_h(208.0, 22.0)
.right_from(state.ids.absolute_scale_text, 10.0)
@ -434,43 +439,6 @@ impl<'a> Widget for SettingsWindow<'a> {
}
// Crosshair Options
// Crosshair Transparency
Text::new("Crosshair")
.down_from(state.ids.absolute_scale_button, 20.0)
.font_size(18)
.font_id(self.fonts.opensans)
.color(TEXT_COLOR)
.set(state.ids.ch_title, ui);
if let Some(new_val) = ImageSlider::continuous(
crosshair_transp,
0.0,
1.0,
self.imgs.slider_indicator,
self.imgs.slider,
)
.w_h(104.0, 22.0)
.down_from(state.ids.ch_transp_text, 8.0)
.track_breadth(12.0)
.slider_length(10.0)
.pad_track((5.0, 5.0))
.set(state.ids.ch_transp_slider, ui)
{
events.push(Event::CrosshairTransp(new_val));
}
Text::new(&format!("{:.2}", crosshair_transp,))
.right_from(state.ids.ch_transp_slider, 8.0)
.font_size(14)
.font_id(self.fonts.opensans)
.color(TEXT_COLOR)
.set(state.ids.ch_transp_value, ui);
Text::new("Transparency")
.right_from(state.ids.ch_3_bg, 20.0)
.font_size(14)
.font_id(self.fonts.opensans)
.color(TEXT_COLOR)
.set(state.ids.ch_transp_text, ui);
// Crosshair Types
// Round
if Button::image(if let CrosshairType::Round = crosshair_type {
@ -600,6 +568,252 @@ impl<'a> Widget for SettingsWindow<'a> {
.color(Some(Color::Rgba(1.0, 1.0, 1.0, 0.6)))
.graphics_for(state.ids.ch_3_bg)
.set(state.ids.crosshair_inner_3, ui);
// Crosshair Transparency Text and Slider
Text::new("Crosshair")
.down_from(state.ids.absolute_scale_button, 20.0)
.font_size(18)
.font_id(self.fonts.opensans)
.color(TEXT_COLOR)
.set(state.ids.ch_title, ui);
Text::new("Transparency")
.right_from(state.ids.ch_3_bg, 20.0)
.font_size(14)
.font_id(self.fonts.opensans)
.color(TEXT_COLOR)
.set(state.ids.ch_transp_text, ui);
if let Some(new_val) = ImageSlider::continuous(
crosshair_transp,
0.0,
1.0,
self.imgs.slider_indicator,
self.imgs.slider,
)
.w_h(104.0, 22.0)
.down_from(state.ids.ch_transp_text, 8.0)
.track_breadth(12.0)
.slider_length(10.0)
.pad_track((5.0, 5.0))
.set(state.ids.ch_transp_slider, ui)
{
events.push(Event::CrosshairTransp(new_val));
}
Text::new(&format!("{:.2}", crosshair_transp,))
.right_from(state.ids.ch_transp_slider, 8.0)
.font_size(14)
.graphics_for(state.ids.ch_transp_slider)
.font_id(self.fonts.opensans)
.color(TEXT_COLOR)
.set(state.ids.ch_transp_value, ui);
// Hotbar text
Text::new("Hotbar")
.down_from(state.ids.ch_1_bg, 20.0)
.font_size(18)
.font_id(self.fonts.opensans)
.color(TEXT_COLOR)
.set(state.ids.hotbar_title, ui);
// Show xp bar
if Button::image(match self.global_state.settings.gameplay.xp_bar {
XpBar::Always => self.imgs.checkbox_checked,
XpBar::OnGain => self.imgs.checkbox,
})
.w_h(18.0, 18.0)
.hover_image(match self.global_state.settings.gameplay.xp_bar {
XpBar::Always => self.imgs.checkbox_checked_mo,
XpBar::OnGain => self.imgs.checkbox_mo,
})
.press_image(match self.global_state.settings.gameplay.xp_bar {
XpBar::Always => self.imgs.checkbox_checked,
XpBar::OnGain => self.imgs.checkbox_press,
})
.down_from(state.ids.hotbar_title, 8.0)
.set(state.ids.show_xpbar_button, ui)
.was_clicked()
{
match self.global_state.settings.gameplay.xp_bar {
XpBar::Always => events.push(Event::ToggleXpBar(XpBar::OnGain)),
XpBar::OnGain => events.push(Event::ToggleXpBar(XpBar::Always)),
}
}
Text::new("Always show Experience Bar")
.right_from(state.ids.show_xpbar_button, 10.0)
.font_size(14)
.font_id(self.fonts.opensans)
.graphics_for(state.ids.show_xpbar_button)
.color(TEXT_COLOR)
.set(state.ids.show_xpbar_text, ui);
// Show Health & Energy Bars
if Button::image(match self.global_state.settings.gameplay.en_bars {
EnBars::Always => self.imgs.checkbox_checked,
EnBars::OnLoss => self.imgs.checkbox,
})
.w_h(18.0, 18.0)
.hover_image(match self.global_state.settings.gameplay.en_bars {
EnBars::Always => self.imgs.checkbox_checked_mo,
EnBars::OnLoss => self.imgs.checkbox_mo,
})
.press_image(match self.global_state.settings.gameplay.en_bars {
EnBars::Always => self.imgs.checkbox_checked,
EnBars::OnLoss => self.imgs.checkbox_press,
})
.down_from(state.ids.show_xpbar_button, 8.0)
.set(state.ids.show_bars_button, ui)
.was_clicked()
{
match self.global_state.settings.gameplay.en_bars {
EnBars::Always => events.push(Event::ToggleEnBars(EnBars::OnLoss)),
EnBars::OnLoss => events.push(Event::ToggleEnBars(EnBars::Always)),
}
}
Text::new("Always show Health and Energy Bars")
.right_from(state.ids.show_bars_button, 10.0)
.font_size(14)
.font_id(self.fonts.opensans)
.graphics_for(state.ids.show_bars_button)
.color(TEXT_COLOR)
.set(state.ids.show_bars_text, ui);
// Show Shortcut Numbers
if Button::image(match self.global_state.settings.gameplay.shortcut_numbers {
ShortcutNumbers::On => self.imgs.checkbox_checked,
ShortcutNumbers::Off => self.imgs.checkbox,
})
.w_h(18.0, 18.0)
.hover_image(match self.global_state.settings.gameplay.shortcut_numbers {
ShortcutNumbers::On => self.imgs.checkbox_checked_mo,
ShortcutNumbers::Off => self.imgs.checkbox_mo,
})
.press_image(match self.global_state.settings.gameplay.shortcut_numbers {
ShortcutNumbers::On => self.imgs.checkbox_checked,
ShortcutNumbers::Off => self.imgs.checkbox_press,
})
.down_from(state.ids.show_bars_button, 8.0)
.set(state.ids.show_shortcuts_button, ui)
.was_clicked()
{
match self.global_state.settings.gameplay.shortcut_numbers {
ShortcutNumbers::On => {
events.push(Event::ToggleShortcutNumbers(ShortcutNumbers::Off))
}
ShortcutNumbers::Off => {
events.push(Event::ToggleShortcutNumbers(ShortcutNumbers::On))
}
}
}
Text::new("Always show Shortcuts")
.right_from(state.ids.show_shortcuts_button, 10.0)
.font_size(14)
.font_id(self.fonts.opensans)
.graphics_for(state.ids.show_shortcuts_button)
.color(TEXT_COLOR)
.set(state.ids.show_shortcuts_text, ui);
// Energybars Numbers
// Hotbar text
Text::new("Energybar Numbers")
.down_from(state.ids.show_shortcuts_button, 20.0)
.font_size(18)
.font_id(self.fonts.opensans)
.color(TEXT_COLOR)
.set(state.ids.bar_numbers_title, ui);
// None
if Button::image(if let BarNumbers::Off = bar_values {
self.imgs.check_checked
} else {
self.imgs.check
})
.w_h(288.0 / 24.0, 288.0 / 24.0)
.hover_image(if let BarNumbers::Off = bar_values {
self.imgs.check_checked_mo
} else {
self.imgs.check_mo
})
.press_image(if let BarNumbers::Off = bar_values {
self.imgs.check_checked
} else {
self.imgs.check_press
})
.down_from(state.ids.bar_numbers_title, 8.0)
.set(state.ids.show_bar_numbers_none_button, ui)
.was_clicked()
{
events.push(Event::ToggleBarNumbers(BarNumbers::Off))
}
Text::new("None")
.right_from(state.ids.show_bar_numbers_none_button, 10.0)
.font_size(14)
.font_id(self.fonts.opensans)
.graphics_for(state.ids.show_bar_numbers_none_button)
.color(TEXT_COLOR)
.set(state.ids.show_bar_numbers_none_text, ui);
// Values
if Button::image(if let BarNumbers::Values = bar_values {
self.imgs.check_checked
} else {
self.imgs.check
})
.w_h(288.0 / 24.0, 288.0 / 24.0)
.hover_image(if let BarNumbers::Values = bar_values {
self.imgs.check_checked_mo
} else {
self.imgs.check_mo
})
.press_image(if let BarNumbers::Values = bar_values {
self.imgs.check_checked
} else {
self.imgs.check_press
})
.down_from(state.ids.show_bar_numbers_none_button, 8.0)
.set(state.ids.show_bar_numbers_values_button, ui)
.was_clicked()
{
events.push(Event::ToggleBarNumbers(BarNumbers::Values))
}
Text::new("Values")
.right_from(state.ids.show_bar_numbers_values_button, 10.0)
.font_size(14)
.font_id(self.fonts.opensans)
.graphics_for(state.ids.show_bar_numbers_values_button)
.color(TEXT_COLOR)
.set(state.ids.show_bar_numbers_values_text, ui);
// Percentages
if Button::image(if let BarNumbers::Percent = bar_values {
self.imgs.check_checked
} else {
self.imgs.check
})
.w_h(288.0 / 24.0, 288.0 / 24.0)
.hover_image(if let BarNumbers::Percent = bar_values {
self.imgs.check_checked_mo
} else {
self.imgs.check_mo
})
.press_image(if let BarNumbers::Percent = bar_values {
self.imgs.check_checked
} else {
self.imgs.check_press
})
.down_from(state.ids.show_bar_numbers_values_button, 8.0)
.set(state.ids.show_bar_numbers_percentage_button, ui)
.was_clicked()
{
events.push(Event::ToggleBarNumbers(BarNumbers::Percent))
}
Text::new("Percentages")
.right_from(state.ids.show_bar_numbers_percentage_button, 10.0)
.font_size(14)
.font_id(self.fonts.opensans)
.graphics_for(state.ids.show_bar_numbers_percentage_button)
.color(TEXT_COLOR)
.set(state.ids.show_bar_numbers_percentage_text, ui);
Rectangle::fill_with([20.0 * 4.0, 1.0 * 4.0], color::TRANSPARENT)
.down_from(state.ids.show_bar_numbers_percentage_button, 8.0)
.set(state.ids.placeholder, ui);
}
// 2) Gameplay Tab --------------------------------

View File

@ -1,48 +1,113 @@
use super::{img_ids::Imgs, Fonts, HP_COLOR, MANA_COLOR, TEXT_COLOR, XP_COLOR};
use super::{
img_ids::Imgs, BarNumbers, EnBars, Fonts, ShortcutNumbers, XpBar, CRITICAL_HP_COLOR,
/*FOCUS_COLOR, RAGE_COLOR,*/ HP_COLOR, LOW_HP_COLOR, MANA_COLOR, TEXT_COLOR, XP_COLOR,
};
use crate::GlobalState;
use common::comp::Stats;
use conrod_core::{
widget::{self, Image, Rectangle, Text},
widget_ids, Colorable, Positionable, Sizeable, Widget, WidgetCommon,
color,
widget::{self, Button, Image, Rectangle, Text},
widget_ids, Color, Colorable, Positionable, Sizeable, Widget, WidgetCommon,
};
use std::time::{Duration, Instant};
widget_ids! {
struct Ids {
health_bar,
health_bar_color,
health_tooltip,
l_click,
death_message_1,
death_message_2,
level_text,
mana_bar,
mana_bar_color,
next_level_text,
r_click,
sb_grid_bg_l,
sb_grid_bg_r,
sb_grid_l,
sb_grid_r,
test,
xp_bar,
xp_bar_progress,
crosshair,
xp_bar_mid,
xp_bar_mid_top,
xp_bar_left,
xp_bar_left_top,
xp_bar_right,
xp_bar_right_top,
xp_bar_filling,
xp_bar_filling_top,
hotbar_align,
xp_bar_subdivision,
m1_slot,
m1_slot_bg,
m1_text,
m1_content,
m2_slot,
m2_slot_bg,
m2_text,
m2_content,
slot1,
slot1_bg,
slot1_text,
slot2,
slot2_bg,
slot2_text,
slot3,
slot3_bg,
slot3_text,
slot4,
slot4_bg,
slot4_text,
slot5,
slot5_bg,
slot5_text,
slot6,
slot6_bg,
slot6_text,
slot7,
slot7_bg,
slot7_text,
slot8,
slot8_bg,
slot8_text,
slot9,
slot9_bg,
slot9_text,
slotq,
slotq_bg,
slotq_text,
healthbar_bg,
healthbar_filling,
health_text,
energybar_bg,
energybar_filling,
energy_text,
level_up,
level_down,
level_align,
level_message,
}
}
pub enum ResourceType {
Mana,
//Rage,
//Focus,
}
#[derive(WidgetCommon)]
pub struct Skillbar<'a> {
global_state: &'a GlobalState,
imgs: &'a Imgs,
_fonts: &'a Fonts,
stats: &'a Stats,
#[conrod(common_builder)]
common: widget::CommonBuilder,
current_resource: ResourceType,
}
impl<'a> Skillbar<'a> {
pub fn new(imgs: &'a Imgs, fonts: &'a Fonts, stats: &'a Stats) -> Self {
pub fn new(
global_state: &'a GlobalState,
imgs: &'a Imgs,
fonts: &'a Fonts,
stats: &'a Stats,
) -> Self {
Self {
imgs,
_fonts: fonts,
stats,
global_state,
current_resource: ResourceType::Mana,
common: widget::CommonBuilder::default(),
}
}
@ -50,18 +115,26 @@ impl<'a> Skillbar<'a> {
pub struct State {
ids: Ids,
}
pub enum Event {}
last_xp_value: f64,
last_level: u32,
last_update_xp: Instant,
last_update_level: Instant,
}
impl<'a> Widget for Skillbar<'a> {
type State = State;
type Style = ();
type Event = Option<Event>;
type Event = ();
fn init_state(&self, id_gen: widget::id::Generator) -> Self::State {
State {
ids: Ids::new(id_gen),
last_xp_value: 0.0,
last_level: 1,
last_update_xp: Instant::now(),
last_update_level: Instant::now(),
}
}
@ -77,107 +150,554 @@ impl<'a> Widget for Skillbar<'a> {
let exp_percentage = self.stats.exp.current() / self.stats.exp.maximum();
let hp_percentage = self.stats.health.current() as f64 / self.stats.health.maximum() as f64;
let mana_percentage = 1.0;
let hp_percentage =
self.stats.health.current() as f64 / self.stats.health.maximum() as f64 * 100.0;
let energy_percentage =
self.stats.energy.current() as f64 / self.stats.energy.maximum() as f64 * 100.0;
// TODO: Only show while aiming with a bow or when casting a spell.
// Crosshair
// Image::new(self.imgs.crosshair)
// .w_h(101.0 * 0.5, 101.0 * 0.5)
// .mid_top_with_margin_on(ui.window, 500.0)
// .set(state.ids.crosshair, ui);
let scale = 2.0;
let bar_values = self.global_state.settings.gameplay.bar_numbers;
let shortcuts = self.global_state.settings.gameplay.shortcut_numbers;
const BG_COLOR: Color = Color::Rgba(1.0, 1.0, 1.0, 0.8);
// Level Up Message
let current_level = self.stats.level.level();
const FADE_IN_LVL: f32 = 1.0;
const FADE_HOLD_LVL: f32 = 3.0;
const FADE_OUT_LVL: f32 = 2.0;
// Fade
// Check if no other popup is displayed and a new one is needed
if state.last_update_level.elapsed()
> Duration::from_secs_f32(FADE_IN_LVL + FADE_HOLD_LVL + FADE_OUT_LVL)
&& state.last_level != current_level
{
// Update last_value
state.update(|s| s.last_level = current_level);
state.update(|s| s.last_update_level = Instant::now());
}
let seconds_level = state.last_update_level.elapsed().as_secs_f32();
let fade_level = if current_level == 1 {
0.0
} else if seconds_level < FADE_IN_LVL {
seconds_level / FADE_IN_LVL
} else if seconds_level < FADE_IN_LVL + FADE_HOLD_LVL {
1.0
} else {
(1.0 - (seconds_level - FADE_IN_LVL - FADE_HOLD_LVL) / FADE_OUT_LVL).max(0.0)
};
// Contents
Rectangle::fill_with([82.0 * 4.0, 40.0 * 4.0], color::TRANSPARENT)
.mid_top_with_margin_on(ui.window, 300.0)
.set(state.ids.level_align, ui);
let level_up_text = format!("Level {}", self.stats.level.level() as u32);
Text::new(&level_up_text)
.middle_of(state.ids.level_align)
.font_size(30)
.color(Color::Rgba(1.0, 1.0, 1.0, fade_level))
.set(state.ids.level_message, ui);
Image::new(self.imgs.level_up)
.w_h(82.0 * 4.0, 9.0 * 4.0)
.mid_top_with_margin_on(state.ids.level_align, 0.0)
.color(Some(Color::Rgba(1.0, 1.0, 1.0, fade_level)))
.graphics_for(state.ids.level_align)
.set(state.ids.level_up, ui);
Image::new(self.imgs.level_down)
.w_h(82.0 * 4.0, 9.0 * 4.0)
.mid_bottom_with_margin_on(state.ids.level_align, 0.0)
.color(Some(Color::Rgba(1.0, 1.0, 1.0, fade_level)))
.graphics_for(state.ids.level_align)
.set(state.ids.level_down, ui);
// Death message
if hp_percentage == 0.0 {
Text::new("You Died")
.mid_top_with_margin_on(ui.window, 60.0)
.font_size(40)
.color(CRITICAL_HP_COLOR)
.set(state.ids.death_message_1, ui);
Text::new("Press L-Mouse to respawn.")
.mid_bottom_with_margin_on(state.ids.death_message_1, -30.0)
.font_size(15)
.color(CRITICAL_HP_COLOR)
.set(state.ids.death_message_2, ui);
}
// Experience-Bar
Image::new(self.imgs.xp_bar)
.w_h(672.0 / 1.5, 29.0 / 1.5)
.mid_bottom_of(ui.window)
.set(state.ids.xp_bar, ui);
match self.global_state.settings.gameplay.xp_bar {
XpBar::Always => {
// Constant Display of the Exp Bar at the bottom of the screen
Image::new(self.imgs.xp_bar_mid)
.w_h(80.0 * scale, 10.0 * scale)
.mid_bottom_with_margin_on(ui.window, 2.0)
.set(state.ids.xp_bar_mid, ui);
Image::new(self.imgs.xp_bar_right)
.w_h(100.0 * scale, 10.0 * scale)
.right_from(state.ids.xp_bar_mid, 0.0)
.set(state.ids.xp_bar_right, ui);
Image::new(self.imgs.xp_bar_left)
.w_h(100.0 * scale, 10.0 * scale)
.left_from(state.ids.xp_bar_mid, 0.0)
.set(state.ids.xp_bar_left, ui);
Image::new(self.imgs.bar_content)
.w_h(260.0 * scale * exp_percentage, 5.0 * scale)
.color(Some(XP_COLOR))
.top_left_with_margins_on(state.ids.xp_bar_left, 2.0 * scale, 10.0 * scale)
.set(state.ids.xp_bar_filling, ui);
// Level Display
Text::new(&level)
.bottom_left_with_margins_on(state.ids.xp_bar_left, 3.5 * scale, 4.0 * scale)
.font_size(10)
.color(Color::Rgba(1.0, 1.0, 1.0, 1.0))
.set(state.ids.level_text, ui);
Text::new(&next_level)
.bottom_right_with_margins_on(state.ids.xp_bar_right, 3.5 * scale, 4.0 * scale)
.font_size(10)
.color(Color::Rgba(1.0, 1.0, 1.0, 1.0))
.set(state.ids.next_level_text, ui);
// M1 Slot
Image::new(self.imgs.skillbar_slot_big)
.w_h(40.0 * scale, 40.0 * scale)
.top_left_with_margins_on(state.ids.xp_bar_mid, -40.0 * scale, 0.0)
.set(state.ids.m1_slot, ui);
}
XpBar::OnGain => {
// Displays the Exp Bar at the top of the screen when exp is gained and fades it out afterwards
const FADE_IN_XP: f32 = 1.0;
const FADE_HOLD_XP: f32 = 3.0;
const FADE_OUT_XP: f32 = 2.0;
let current_xp = self.stats.exp.current();
// Check if no other popup is displayed and a new one is needed
if state.last_update_xp.elapsed()
> Duration::from_secs_f32(FADE_IN_XP + FADE_HOLD_XP + FADE_OUT_XP)
&& state.last_xp_value != current_xp
{
// Update last_value
state.update(|s| s.last_xp_value = current_xp);
state.update(|s| s.last_update_xp = Instant::now());
}
Rectangle::fill_with([406.0 * (exp_percentage), 5.0], XP_COLOR) // "W=406*[Exp. %]"
.top_left_with_margins_on(state.ids.xp_bar, 5.0, 21.0)
.set(state.ids.xp_bar_progress, ui);
let seconds_xp = state.last_update_xp.elapsed().as_secs_f32();
let fade_xp = if current_xp == 0.0 {
0.0
} else if seconds_xp < FADE_IN_XP {
seconds_xp / FADE_IN_XP
} else if seconds_xp < FADE_IN_XP + FADE_HOLD_XP {
1.0
} else {
(1.0 - (seconds_xp - FADE_IN_XP - FADE_HOLD_XP) / FADE_OUT_XP).max(0.0)
};
// Hotbar parts
Image::new(self.imgs.xp_bar_mid)
.w_h(80.0 * scale * 1.5, 10.0 * scale * 1.5)
.mid_top_with_margin_on(ui.window, 20.0)
.color(Some(Color::Rgba(1.0, 1.0, 1.0, fade_xp)))
.set(state.ids.xp_bar_mid_top, ui);
Image::new(self.imgs.xp_bar_right)
.w_h(100.0 * scale * 1.5, 10.0 * scale * 1.5)
.right_from(state.ids.xp_bar_mid_top, 0.0)
.color(Some(Color::Rgba(1.0, 1.0, 1.0, fade_xp)))
.set(state.ids.xp_bar_right_top, ui);
Image::new(self.imgs.xp_bar_left)
.w_h(100.0 * scale * 1.5, 10.0 * scale * 1.5)
.left_from(state.ids.xp_bar_mid_top, 0.0)
.color(Some(Color::Rgba(1.0, 1.0, 1.0, fade_xp)))
.set(state.ids.xp_bar_left_top, ui);
Image::new(self.imgs.bar_content)
.w_h(260.0 * scale * 1.5 * exp_percentage, 6.0 * scale * 1.5)
.color(Some(Color::Rgba(0.59, 0.41, 0.67, fade_xp)))
.top_left_with_margins_on(
state.ids.xp_bar_left_top,
2.0 * scale * 1.5,
10.0 * scale * 1.5,
)
.set(state.ids.xp_bar_filling_top, ui);
// Level Display
Text::new(&level)
.bottom_left_with_margins_on(
state.ids.xp_bar_left_top,
3.0 * scale * 1.5,
4.0 * scale * 1.5,
)
.font_size(17)
.color(Color::Rgba(1.0, 1.0, 1.0, fade_xp))
.set(state.ids.level_text, ui);
Text::new(&next_level)
.bottom_right_with_margins_on(
state.ids.xp_bar_right_top,
3.0 * scale * 1.5,
4.0 * scale * 1.5,
)
.font_size(17)
.color(Color::Rgba(1.0, 1.0, 1.0, fade_xp))
.set(state.ids.next_level_text, ui);
// Alignment for hotbar
Rectangle::fill_with([80.0 * scale, 1.0], color::TRANSPARENT)
.mid_bottom_with_margin_on(ui.window, 9.0)
.set(state.ids.hotbar_align, ui);
// M1 Slot
Image::new(self.imgs.skillbar_slot_big)
.w_h(40.0 * scale, 40.0 * scale)
.top_left_with_margins_on(state.ids.hotbar_align, -40.0 * scale, 0.0)
.set(state.ids.m1_slot, ui);
}
}
// M1 Slot
Image::new(self.imgs.skillbar_slot_big_bg)
.w_h(37.0 * scale, 37.0 * scale)
.color(Some(BG_COLOR))
.middle_of(state.ids.m1_slot)
.set(state.ids.m1_slot_bg, ui);
Button::image(self.imgs.twohhammer_m1) // Insert Icon here
.w_h(38.0 * scale, 38.0 * scale)
.middle_of(state.ids.m1_slot_bg)
.set(state.ids.m1_content, ui);
// M2 Slot
Image::new(self.imgs.skillbar_slot_big)
.w_h(40.0 * scale, 40.0 * scale)
.right_from(state.ids.m1_slot, 0.0)
.set(state.ids.m2_slot, ui);
Image::new(self.imgs.skillbar_slot_big_bg)
.w_h(37.0 * scale, 37.0 * scale)
.color(Some(BG_COLOR))
.middle_of(state.ids.m2_slot)
.set(state.ids.m2_slot_bg, ui);
Button::image(self.imgs.twohhammer_m2) // Insert Icon here
.w_h(38.0 * scale, 38.0 * scale)
.middle_of(state.ids.m2_slot_bg)
.set(state.ids.m2_content, ui);
//Slot 5
Image::new(self.imgs.skillbar_slot)
.w_h(20.0 * scale, 20.0 * scale)
.bottom_left_with_margins_on(state.ids.m1_slot, 0.0, -20.0 * scale)
.set(state.ids.slot5, ui);
Image::new(self.imgs.skillbar_slot_bg)
.w_h(19.0 * scale, 19.0 * scale)
.color(Some(BG_COLOR))
.middle_of(state.ids.slot5)
.set(state.ids.slot5_bg, ui);
// Slot 4
Image::new(self.imgs.skillbar_slot)
.w_h(20.0 * scale, 20.0 * scale)
.left_from(state.ids.slot5, 0.0)
.set(state.ids.slot4, ui);
Image::new(self.imgs.skillbar_slot_bg)
.w_h(19.0 * scale, 19.0 * scale)
.color(Some(BG_COLOR))
.middle_of(state.ids.slot4)
.set(state.ids.slot4_bg, ui);
// Slot 3
Image::new(self.imgs.skillbar_slot)
.w_h(20.0 * scale, 20.0 * scale)
.left_from(state.ids.slot4, 0.0)
.set(state.ids.slot3, ui);
Image::new(self.imgs.skillbar_slot_bg)
.w_h(19.0 * scale, 19.0 * scale)
.color(Some(BG_COLOR))
.middle_of(state.ids.slot3)
.set(state.ids.slot3_bg, ui);
// Slot 2
Image::new(self.imgs.skillbar_slot)
.w_h(20.0 * scale, 20.0 * scale)
.left_from(state.ids.slot3, 0.0)
.set(state.ids.slot2, ui);
Image::new(self.imgs.skillbar_slot_bg)
.w_h(19.0 * scale, 19.0 * scale)
.color(Some(BG_COLOR))
.middle_of(state.ids.slot2)
.set(state.ids.slot2_bg, ui);
// Slot 1
Image::new(self.imgs.skillbar_slot_l)
.w_h(20.0 * scale, 20.0 * scale)
.left_from(state.ids.slot2, 0.0)
.set(state.ids.slot1, ui);
Image::new(self.imgs.skillbar_slot_bg)
.w_h(19.0 * scale, 19.0 * scale)
.color(Some(BG_COLOR))
.middle_of(state.ids.slot1)
.set(state.ids.slot1_bg, ui);
// Slot 6
Image::new(self.imgs.skillbar_slot)
.w_h(20.0 * scale, 20.0 * scale)
.bottom_right_with_margins_on(state.ids.m2_slot, 0.0, -20.0 * scale)
.set(state.ids.slot6, ui);
Image::new(self.imgs.skillbar_slot_bg)
.w_h(19.0 * scale, 19.0 * scale)
.color(Some(BG_COLOR))
.middle_of(state.ids.slot6)
.set(state.ids.slot6_bg, ui);
// Slot 7
Image::new(self.imgs.skillbar_slot)
.w_h(20.0 * scale, 20.0 * scale)
.right_from(state.ids.slot6, 0.0)
.set(state.ids.slot7, ui);
Image::new(self.imgs.skillbar_slot_bg)
.w_h(19.0 * scale, 19.0 * scale)
.color(Some(BG_COLOR))
.middle_of(state.ids.slot7)
.set(state.ids.slot7_bg, ui);
// Slot 8
Image::new(self.imgs.skillbar_slot)
.w_h(20.0 * scale, 20.0 * scale)
.right_from(state.ids.slot7, 0.0)
.set(state.ids.slot8, ui);
Image::new(self.imgs.skillbar_slot_bg)
.w_h(19.0 * scale, 19.0 * scale)
.color(Some(BG_COLOR))
.middle_of(state.ids.slot8)
.set(state.ids.slot8_bg, ui);
// Slot 9
Image::new(self.imgs.skillbar_slot)
.w_h(20.0 * scale, 20.0 * scale)
.right_from(state.ids.slot8, 0.0)
.set(state.ids.slot9, ui);
Image::new(self.imgs.skillbar_slot_bg)
.w_h(19.0 * scale, 19.0 * scale)
.color(Some(BG_COLOR))
.middle_of(state.ids.slot9)
.set(state.ids.slot9_bg, ui);
// Quickslot
Image::new(self.imgs.skillbar_slot_r)
.w_h(20.0 * scale, 20.0 * scale)
.right_from(state.ids.slot9, 0.0)
.set(state.ids.slotq, ui);
Image::new(self.imgs.skillbar_slot_bg)
.w_h(19.0 * scale, 19.0 * scale)
.color(Some(BG_COLOR))
.middle_of(state.ids.slotq)
.set(state.ids.slotq_bg, ui);
// Shortcuts
// Left Grid
Image::new(self.imgs.sb_grid)
.w_h(280.0 / 1.5, 56.0 / 1.5)
.up_from(state.ids.xp_bar, 0.0)
.align_left_of(state.ids.xp_bar)
.set(state.ids.sb_grid_l, ui);
if let ShortcutNumbers::On = shortcuts {
Text::new("1")
.top_right_with_margins_on(state.ids.slot1_bg, 1.0, 1.0)
.font_size(8)
.color(TEXT_COLOR)
.set(state.ids.slot1_text, ui);
Text::new("2")
.top_right_with_margins_on(state.ids.slot2_bg, 1.0, 1.0)
.font_size(8)
.color(TEXT_COLOR)
.set(state.ids.slot2_text, ui);
Text::new("3")
.top_right_with_margins_on(state.ids.slot3_bg, 1.0, 1.0)
.font_size(8)
.color(TEXT_COLOR)
.set(state.ids.slot3_text, ui);
Text::new("4")
.top_right_with_margins_on(state.ids.slot4_bg, 1.0, 1.0)
.font_size(8)
.color(TEXT_COLOR)
.set(state.ids.slot4_text, ui);
Text::new("5")
.top_right_with_margins_on(state.ids.slot5_bg, 1.0, 1.0)
.font_size(8)
.color(TEXT_COLOR)
.set(state.ids.slot5_text, ui);
Text::new("M1")
.top_left_with_margins_on(state.ids.m1_slot, 5.0, 5.0)
.font_size(8)
.color(TEXT_COLOR)
.set(state.ids.m1_text, ui);
Text::new("M2")
.top_right_with_margins_on(state.ids.m2_slot, 5.0, 5.0)
.font_size(8)
.color(TEXT_COLOR)
.set(state.ids.m2_text, ui);
Text::new("6")
.top_left_with_margins_on(state.ids.slot6_bg, 1.0, 1.0)
.font_size(8)
.color(TEXT_COLOR)
.set(state.ids.slot6_text, ui);
Text::new("7")
.top_left_with_margins_on(state.ids.slot7_bg, 1.0, 1.0)
.font_size(8)
.color(TEXT_COLOR)
.set(state.ids.slot7_text, ui);
Text::new("8")
.top_left_with_margins_on(state.ids.slot8_bg, 1.0, 1.0)
.font_size(8)
.color(TEXT_COLOR)
.set(state.ids.slot8_text, ui);
Text::new("9")
.top_left_with_margins_on(state.ids.slot9_bg, 1.0, 1.0)
.font_size(8)
.color(TEXT_COLOR)
.set(state.ids.slot9_text, ui);
Text::new("Q")
.top_left_with_margins_on(state.ids.slotq_bg, 1.0, 1.0)
.font_size(8)
.color(TEXT_COLOR)
.set(state.ids.slotq_text, ui);
};
Image::new(self.imgs.sb_grid_bg)
.w_h(280.0 / 1.5, 56.0 / 1.5)
.middle_of(state.ids.sb_grid_l)
.set(state.ids.sb_grid_bg_l, ui);
// Right Grid
Image::new(self.imgs.sb_grid)
.w_h(280.0 / 1.5, 56.0 / 1.5)
.up_from(state.ids.xp_bar, 0.0)
.align_right_of(state.ids.xp_bar)
.set(state.ids.sb_grid_r, ui);
Image::new(self.imgs.sb_grid_bg)
.w_h(280.0 / 1.5, 56.0 / 1.5)
.middle_of(state.ids.sb_grid_r)
.set(state.ids.sb_grid_bg_r, ui);
// Right and Left Click
Image::new(self.imgs.l_click)
.w_h(56.0 / 1.5, 80.0 / 1.5)
.right_from(state.ids.sb_grid_bg_l, 0.0)
.align_bottom_of(state.ids.sb_grid_bg_l)
.set(state.ids.l_click, ui);
Image::new(self.imgs.r_click)
.w_h(56.0 / 1.5, 80.0 / 1.5)
.left_from(state.ids.sb_grid_bg_r, 0.0)
.align_bottom_of(state.ids.sb_grid_bg_r)
.set(state.ids.r_click, ui);
// Health Bar
Image::new(self.imgs.health_bar)
.w_h(1120.0 / 6.0, 96.0 / 6.0)
.left_from(state.ids.l_click, 0.0)
.align_top_of(state.ids.l_click)
.set(state.ids.health_bar, ui);
// Filling
Rectangle::fill_with([182.0 * hp_percentage, 6.0], HP_COLOR) // "W=182.0 * [Health. %]"
.top_right_with_margins_on(state.ids.health_bar, 5.0, 0.0)
.set(state.ids.health_bar_color, ui);
// Mana Bar
Image::new(self.imgs.mana_bar)
.w_h(1120.0 / 6.0, 96.0 / 6.0)
.right_from(state.ids.r_click, 0.0)
.align_top_of(state.ids.r_click)
.set(state.ids.mana_bar, ui);
// Filling
Rectangle::fill_with([182.0 * mana_percentage, 6.0], MANA_COLOR) // "W=182.0 * [Mana. %]"
.top_left_with_margins_on(state.ids.mana_bar, 5.0, 0.0)
.set(state.ids.mana_bar_color, ui);
// Buffs/Debuffs
// Option to show Energy Bars only on loss or Always
match self.global_state.settings.gameplay.en_bars {
EnBars::OnLoss => {
if { self.stats.health.current() < self.stats.health.maximum() } || {
self.stats.energy.current() < self.stats.energy.maximum()
} {
// Lifebar
Image::new(self.imgs.healthbar_bg)
.w_h(100.0 * scale, 20.0 * scale)
.top_left_with_margins_on(state.ids.m1_slot, 0.0, -100.0 * scale)
.set(state.ids.healthbar_bg, ui);
Image::new(self.imgs.bar_content)
.w_h(97.0 * scale * hp_percentage / 100.0, 16.0 * scale)
.color(Some(if hp_percentage <= 20.0 {
CRITICAL_HP_COLOR
} else if hp_percentage <= 40.0 {
LOW_HP_COLOR
} else {
HP_COLOR
}))
.top_right_with_margins_on(state.ids.healthbar_bg, 2.0 * scale, 1.0 * scale)
.set(state.ids.healthbar_filling, ui);
// Energybar
Image::new(self.imgs.energybar_bg)
.w_h(100.0 * scale, 20.0 * scale)
.top_right_with_margins_on(state.ids.m2_slot, 0.0, -100.0 * scale)
.set(state.ids.energybar_bg, ui);
Image::new(self.imgs.bar_content)
.w_h(97.0 * scale * energy_percentage / 100.0, 16.0 * scale)
.top_left_with_margins_on(state.ids.energybar_bg, 2.0 * scale, 1.0 * scale)
.color(Some(match self.current_resource {
ResourceType::Mana => MANA_COLOR,
//ResourceType::Focus => FOCUS_COLOR,
//ResourceType::Rage => RAGE_COLOR,
}))
.set(state.ids.energybar_filling, ui);
// Bar Text
// Values
if let BarNumbers::Values = bar_values {
let hp_text = format!(
"{}/{}",
self.stats.health.current() as u32,
self.stats.health.maximum() as u32
);
Text::new(&hp_text)
.mid_top_with_margin_on(state.ids.healthbar_bg, 5.0 * scale)
.font_size(14)
.color(TEXT_COLOR)
.set(state.ids.health_text, ui);
let energy_text = format!(
"{}/{}",
self.stats.energy.current() as u32,
self.stats.energy.maximum() as u32
);
Text::new(&energy_text)
.mid_top_with_margin_on(state.ids.energybar_bg, 5.0 * scale)
.font_size(14)
.color(TEXT_COLOR)
.set(state.ids.energy_text, ui);
}
//Percentages
if let BarNumbers::Percent = bar_values {
let hp_text = format!("{}%", hp_percentage as u32);
Text::new(&hp_text)
.mid_top_with_margin_on(state.ids.healthbar_bg, 5.0 * scale)
.font_size(14)
.color(TEXT_COLOR)
.set(state.ids.health_text, ui);
let energy_text = format!("{}%", energy_percentage as u32);
Text::new(&energy_text)
.mid_top_with_margin_on(state.ids.energybar_bg, 5.0 * scale)
.font_size(14)
.color(TEXT_COLOR)
.set(state.ids.energy_text, ui);
}
} else {
// Lifebar
Image::new(self.imgs.healthbar_bg)
.w_h(100.0 * scale, 20.0 * scale)
.color(Some(Color::Rgba(1.0, 1.0, 1.0, 0.8)))
.top_left_with_margins_on(state.ids.m1_slot, 0.0, -100.0 * scale)
.set(state.ids.healthbar_bg, ui);
// Energybar
Image::new(self.imgs.energybar_bg)
.w_h(100.0 * scale, 20.0 * scale)
.color(Some(Color::Rgba(1.0, 1.0, 1.0, 0.8)))
.top_right_with_margins_on(state.ids.m2_slot, 0.0, -100.0 * scale)
.set(state.ids.energybar_bg, ui);
}
}
EnBars::Always => {
// Lifebar
Image::new(self.imgs.healthbar_bg)
.w_h(100.0 * scale, 20.0 * scale)
.top_left_with_margins_on(state.ids.m1_slot, 0.0, -100.0 * scale)
.set(state.ids.healthbar_bg, ui);
Image::new(self.imgs.bar_content)
.w_h(97.0 * scale * hp_percentage / 100.0, 16.0 * scale)
.color(Some(if hp_percentage <= 20.0 {
CRITICAL_HP_COLOR
} else if hp_percentage <= 40.0 {
LOW_HP_COLOR
} else {
HP_COLOR
}))
.top_right_with_margins_on(state.ids.healthbar_bg, 2.0 * scale, 1.0 * scale)
.set(state.ids.healthbar_filling, ui);
// Energybar
Image::new(self.imgs.energybar_bg)
.w_h(100.0 * scale, 20.0 * scale)
.top_right_with_margins_on(state.ids.m2_slot, 0.0, -100.0 * scale)
.set(state.ids.energybar_bg, ui);
Image::new(self.imgs.bar_content)
.w_h(97.0 * scale * energy_percentage / 100.0, 16.0 * scale)
.top_left_with_margins_on(state.ids.energybar_bg, 2.0 * scale, 1.0 * scale)
.color(Some(match self.current_resource {
ResourceType::Mana => MANA_COLOR,
//ResourceType::Focus => FOCUS_COLOR,
//ResourceType::Rage => RAGE_COLOR,
}))
.set(state.ids.energybar_filling, ui);
// Bar Text
// Values
if let BarNumbers::Values = bar_values {
let hp_text = format!(
"{}/{}",
self.stats.health.current() as u32,
self.stats.health.maximum() as u32
);
Text::new(&hp_text)
.mid_top_with_margin_on(state.ids.healthbar_bg, 5.0 * scale)
.font_size(14)
.color(TEXT_COLOR)
.set(state.ids.health_text, ui);
let energy_text = format!(
"{}/{}",
self.stats.energy.current() as u32,
self.stats.energy.maximum() as u32
);
Text::new(&energy_text)
.mid_top_with_margin_on(state.ids.energybar_bg, 5.0 * scale)
.font_size(14)
.color(TEXT_COLOR)
.set(state.ids.energy_text, ui);
}
//Percentages
if let BarNumbers::Percent = bar_values {
let hp_text = format!("{}%", hp_percentage as u32);
Text::new(&hp_text)
.mid_top_with_margin_on(state.ids.healthbar_bg, 5.0 * scale)
.font_size(14)
.color(TEXT_COLOR)
.set(state.ids.health_text, ui);
let energy_text = format!("{}%", energy_percentage as u32);
Text::new(&energy_text)
.mid_top_with_margin_on(state.ids.energybar_bg, 5.0 * scale)
.font_size(14)
.color(TEXT_COLOR)
.set(state.ids.energy_text, ui);
}
}
}
// Buffs
// Add debuff slots above the health bar
// Add buff slots above the mana bar
// Debuffs
// Level Display
Text::new(&level)
.left_from(state.ids.xp_bar, -15.0)
.font_size(10)
.color(TEXT_COLOR)
.set(state.ids.level_text, ui);
Text::new(&next_level)
.right_from(state.ids.xp_bar, -15.0)
.font_size(10)
.color(TEXT_COLOR)
.set(state.ids.next_level_text, ui);
None
}
}

View File

@ -1,4 +1,4 @@
#![feature(drain_filter)]
#![feature(duration_float, drain_filter)]
#![recursion_limit = "2048"]
#[cfg(feature = "discord")]

View File

@ -19,7 +19,7 @@ use common::{
};
use dot_vox::DotVoxData;
use hashbrown::HashMap;
use log::warn;
use log::debug;
use specs::{Entity as EcsEntity, Join};
use std::f32;
use vek::*;
@ -913,7 +913,7 @@ impl FigureMgr {
renderer.render_figure(model, globals, locals, bone_consts, lights);
} else {
warn!("Body has no saved figure");
debug!("Body has no saved figure");
}
}
}

View File

@ -345,6 +345,22 @@ impl PlayState for SessionState {
global_state.settings.gameplay.crosshair_type = crosshair_type;
global_state.settings.save_to_file_warn();
}
HudEvent::ToggleXpBar(xp_bar) => {
global_state.settings.gameplay.xp_bar = xp_bar;
global_state.settings.save_to_file_warn();
}
HudEvent::ToggleEnBars(en_bars) => {
global_state.settings.gameplay.en_bars = en_bars;
global_state.settings.save_to_file_warn();
}
HudEvent::ToggleBarNumbers(bar_numbers) => {
global_state.settings.gameplay.bar_numbers = bar_numbers;
global_state.settings.save_to_file_warn();
}
HudEvent::ToggleShortcutNumbers(shortcut_numbers) => {
global_state.settings.gameplay.shortcut_numbers = shortcut_numbers;
global_state.settings.save_to_file_warn();
}
HudEvent::UiScale(scale_change) => {
global_state.settings.gameplay.ui_scale =
self.hud.scale_change(scale_change);

View File

@ -1,4 +1,8 @@
use crate::{hud::CrosshairType, ui::ScaleMode, window::KeyMouse};
use crate::{
hud::{BarNumbers, CrosshairType, EnBars, ShortcutNumbers, XpBar},
ui::ScaleMode,
window::KeyMouse,
};
use directories::ProjectDirs;
use glutin::{MouseButton, VirtualKeyCode};
use log::warn;
@ -80,6 +84,10 @@ pub struct GameplaySettings {
pub zoom_sensitivity: u32,
pub crosshair_transp: f32,
pub crosshair_type: CrosshairType,
pub xp_bar: XpBar,
pub en_bars: EnBars,
pub shortcut_numbers: ShortcutNumbers,
pub bar_numbers: BarNumbers,
pub ui_scale: ScaleMode,
}
@ -90,6 +98,10 @@ impl Default for GameplaySettings {
zoom_sensitivity: 100,
crosshair_transp: 0.6,
crosshair_type: CrosshairType::Round,
xp_bar: XpBar::OnGain,
en_bars: EnBars::OnLoss,
shortcut_numbers: ShortcutNumbers::On,
bar_numbers: BarNumbers::Off,
ui_scale: ScaleMode::RelativeToWindow([1920.0, 1080.0].into()),
}
}