mirror of
https://gitlab.com/veloren/veloren.git
synced 2024-08-30 18:12:32 +00:00
Initial implementation of buffs UI
player buffs animation more testing debuffs sorting and display limit fix overhead buffs fix WIP buff removal function fmt Update buffs.rs Now with compiling: WIP group UI buffs positioning Update group.rs Update group.rs Small optimizations. Fixed positioning of buffs in group panel. Broke buff tooltips in group panel. buff frame visuals added setting for displaying buffs at minimap
This commit is contained in:
@ -1,6 +1,6 @@
|
|||||||
ItemDef(
|
ItemDef(
|
||||||
name: "Apple Stick",
|
name: "Apple Stick",
|
||||||
description: "Restores 20 Health",
|
description: "Restores 25 Health",
|
||||||
kind: Consumable(
|
kind: Consumable(
|
||||||
kind: "AppleStick",
|
kind: "AppleStick",
|
||||||
effect: Health((
|
effect: Health((
|
||||||
|
BIN
assets/voxygen/element/animation/buff_frame/1.png
(Stored with Git LFS)
Normal file
BIN
assets/voxygen/element/animation/buff_frame/1.png
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
assets/voxygen/element/animation/buff_frame/2.png
(Stored with Git LFS)
Normal file
BIN
assets/voxygen/element/animation/buff_frame/2.png
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
assets/voxygen/element/animation/buff_frame/3.png
(Stored with Git LFS)
Normal file
BIN
assets/voxygen/element/animation/buff_frame/3.png
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
assets/voxygen/element/animation/buff_frame/4.png
(Stored with Git LFS)
Normal file
BIN
assets/voxygen/element/animation/buff_frame/4.png
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
assets/voxygen/element/animation/buff_frame/5.png
(Stored with Git LFS)
Normal file
BIN
assets/voxygen/element/animation/buff_frame/5.png
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
assets/voxygen/element/animation/buff_frame/6.png
(Stored with Git LFS)
Normal file
BIN
assets/voxygen/element/animation/buff_frame/6.png
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
assets/voxygen/element/animation/buff_frame/7.png
(Stored with Git LFS)
Normal file
BIN
assets/voxygen/element/animation/buff_frame/7.png
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
assets/voxygen/element/animation/buff_frame/8.png
(Stored with Git LFS)
Normal file
BIN
assets/voxygen/element/animation/buff_frame/8.png
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
assets/voxygen/element/icons/de_buffs/debuff_bleed_0.png
(Stored with Git LFS)
Normal file
BIN
assets/voxygen/element/icons/de_buffs/debuff_bleed_0.png
(Stored with Git LFS)
Normal file
Binary file not shown.
@ -291,6 +291,8 @@ magically infused items?"#,
|
|||||||
"hud.settings.transparency": "Transparency",
|
"hud.settings.transparency": "Transparency",
|
||||||
"hud.settings.hotbar": "Hotbar",
|
"hud.settings.hotbar": "Hotbar",
|
||||||
"hud.settings.toggle_shortcuts": "Toggle Shortcuts",
|
"hud.settings.toggle_shortcuts": "Toggle Shortcuts",
|
||||||
|
"hud.settings.buffs_skillbar": "Buffs at Skillbar",
|
||||||
|
"hud.settings.buffs_mmap": "Buffs at Minimap",
|
||||||
"hud.settings.toggle_bar_experience": "Toggle Experience Bar",
|
"hud.settings.toggle_bar_experience": "Toggle Experience Bar",
|
||||||
"hud.settings.scrolling_combat_text": "Scrolling Combat Text",
|
"hud.settings.scrolling_combat_text": "Scrolling Combat Text",
|
||||||
"hud.settings.single_damage_number": "Single Damage Numbers",
|
"hud.settings.single_damage_number": "Single Damage Numbers",
|
||||||
@ -343,9 +345,9 @@ magically infused items?"#,
|
|||||||
"hud.settings.refresh_rate": "Refresh Rate",
|
"hud.settings.refresh_rate": "Refresh Rate",
|
||||||
"hud.settings.save_window_size": "Save window size",
|
"hud.settings.save_window_size": "Save window size",
|
||||||
"hud.settings.lighting_rendering_mode": "Lighting Rendering Mode",
|
"hud.settings.lighting_rendering_mode": "Lighting Rendering Mode",
|
||||||
"hud.settings.lighting_rendering_mode.ashikhmin": "Type A",
|
"hud.settings.lighting_rendering_mode.ashikhmin": "Type A - High ",
|
||||||
"hud.settings.lighting_rendering_mode.blinnphong": "Type B",
|
"hud.settings.lighting_rendering_mode.blinnphong": "Type B - Medium",
|
||||||
"hud.settings.lighting_rendering_mode.lambertian": "Type L",
|
"hud.settings.lighting_rendering_mode.lambertian": "Type L - Cheap",
|
||||||
"hud.settings.shadow_rendering_mode": "Shadow Rendering Mode",
|
"hud.settings.shadow_rendering_mode": "Shadow Rendering Mode",
|
||||||
"hud.settings.shadow_rendering_mode.none": "None",
|
"hud.settings.shadow_rendering_mode.none": "None",
|
||||||
"hud.settings.shadow_rendering_mode.cheap": "Cheap",
|
"hud.settings.shadow_rendering_mode.cheap": "Cheap",
|
||||||
@ -509,6 +511,16 @@ Protection
|
|||||||
"esc_menu.quit_game": "Quit Game",
|
"esc_menu.quit_game": "Quit Game",
|
||||||
/// End Escape Menu Section
|
/// End Escape Menu Section
|
||||||
|
|
||||||
|
/// Buffs and Debuffs
|
||||||
|
"buff.remove": "Click to remove",
|
||||||
|
"buff.title.missing": "Missing Title",
|
||||||
|
"buff.desc.missing": "Missing Description",
|
||||||
|
// Buffs
|
||||||
|
"buff.title.heal_test": "Heal Test",
|
||||||
|
"buff.desc.heal_test": "This is a test buff to test healing.",
|
||||||
|
// Debuffs
|
||||||
|
"debuff.title.bleed_test": "Bleed Test",
|
||||||
|
"debuff.desc.bleed_test": "This is a test debuff to test bleeding.",
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
||||||
|
@ -37,6 +37,7 @@ use common::{
|
|||||||
terrain::{block::Block, neighbors, TerrainChunk, TerrainChunkSize},
|
terrain::{block::Block, neighbors, TerrainChunk, TerrainChunkSize},
|
||||||
vol::RectVolSize,
|
vol::RectVolSize,
|
||||||
};
|
};
|
||||||
|
use comp::BuffId;
|
||||||
use futures_executor::block_on;
|
use futures_executor::block_on;
|
||||||
use futures_timer::Delay;
|
use futures_timer::Delay;
|
||||||
use futures_util::{select, FutureExt};
|
use futures_util::{select, FutureExt};
|
||||||
@ -631,6 +632,12 @@ impl Client {
|
|||||||
self.send_msg(ClientGeneral::ControlEvent(ControlEvent::DisableLantern));
|
self.send_msg(ClientGeneral::ControlEvent(ControlEvent::DisableLantern));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn remove_buff(&mut self, buff_id: BuffId) {
|
||||||
|
self.send_msg(ClientGeneral::ControlEvent(ControlEvent::RemoveBuff(
|
||||||
|
buff_id,
|
||||||
|
)));
|
||||||
|
}
|
||||||
|
|
||||||
pub fn max_group_size(&self) -> u32 { self.max_group_size }
|
pub fn max_group_size(&self) -> u32 { self.max_group_size }
|
||||||
|
|
||||||
pub fn group_invite(&self) -> Option<(Uid, std::time::Instant, std::time::Duration)> {
|
pub fn group_invite(&self) -> Option<(Uid, std::time::Instant, std::time::Duration)> {
|
||||||
|
@ -151,16 +151,10 @@ impl Buff {
|
|||||||
pub fn new(id: BuffId, cat_ids: Vec<BuffCategoryId>, source: BuffSource) -> Self {
|
pub fn new(id: BuffId, cat_ids: Vec<BuffCategoryId>, source: BuffSource) -> Self {
|
||||||
let (effects, time) = match id {
|
let (effects, time) = match id {
|
||||||
BuffId::Bleeding { strength, duration } => (
|
BuffId::Bleeding { strength, duration } => (
|
||||||
vec![
|
vec![BuffEffect::HealthChangeOverTime {
|
||||||
BuffEffect::HealthChangeOverTime {
|
|
||||||
rate: -strength,
|
rate: -strength,
|
||||||
accumulated: 0.0,
|
accumulated: 0.0,
|
||||||
},
|
}],
|
||||||
// This effect is for testing purposes
|
|
||||||
BuffEffect::NameChange {
|
|
||||||
prefix: String::from("Injured "),
|
|
||||||
},
|
|
||||||
],
|
|
||||||
duration,
|
duration,
|
||||||
),
|
),
|
||||||
BuffId::Regeneration { strength, duration } => (
|
BuffId::Regeneration { strength, duration } => (
|
||||||
|
@ -1,4 +1,8 @@
|
|||||||
use crate::{comp::inventory::slot::Slot, sync::Uid, util::Dir};
|
use crate::{
|
||||||
|
comp::{inventory::slot::Slot, BuffId},
|
||||||
|
sync::Uid,
|
||||||
|
util::Dir,
|
||||||
|
};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use specs::{Component, FlaggedStorage};
|
use specs::{Component, FlaggedStorage};
|
||||||
use specs_idvs::IdvStorage;
|
use specs_idvs::IdvStorage;
|
||||||
@ -37,6 +41,7 @@ pub enum ControlEvent {
|
|||||||
Unmount,
|
Unmount,
|
||||||
InventoryManip(InventoryManip),
|
InventoryManip(InventoryManip),
|
||||||
GroupManip(GroupManip),
|
GroupManip(GroupManip),
|
||||||
|
RemoveBuff(BuffId),
|
||||||
Respawn,
|
Respawn,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -684,7 +684,7 @@ impl<'a> System<'a> for Sys {
|
|||||||
for (_invite, /*alignment,*/ agent, controller) in
|
for (_invite, /*alignment,*/ agent, controller) in
|
||||||
(&invites, /*&alignments,*/ &mut agents, &mut controllers).join()
|
(&invites, /*&alignments,*/ &mut agents, &mut controllers).join()
|
||||||
{
|
{
|
||||||
let accept = false; // set back to "matches!(alignment, Alignment::Npc)" when we got better NPC recruitment mechanics
|
let accept = true; // set back to "matches!(alignment, Alignment::Npc)" when we got better NPC recruitment mechanics
|
||||||
if accept {
|
if accept {
|
||||||
// Clear agent comp
|
// Clear agent comp
|
||||||
*agent = Agent::default();
|
*agent = Agent::default();
|
||||||
|
@ -62,7 +62,7 @@ impl<'a> System<'a> for Sys {
|
|||||||
BuffEffect::HealthChangeOverTime { rate, accumulated } => {
|
BuffEffect::HealthChangeOverTime { rate, accumulated } => {
|
||||||
*accumulated += *rate * buff_delta;
|
*accumulated += *rate * buff_delta;
|
||||||
// Apply only 0.5 or higher damage
|
// Apply only 0.5 or higher damage
|
||||||
if accumulated.abs() > 5.0 {
|
if accumulated.abs() > 50.0 {
|
||||||
let cause = if *accumulated > 0.0 {
|
let cause = if *accumulated > 0.0 {
|
||||||
HealthSource::Healing { by: buff_owner }
|
HealthSource::Healing { by: buff_owner }
|
||||||
} else {
|
} else {
|
||||||
|
@ -157,12 +157,31 @@ impl<'a> System<'a> for Sys {
|
|||||||
buff_change: buff::BuffChange::Add(buff::Buff::new(
|
buff_change: buff::BuffChange::Add(buff::Buff::new(
|
||||||
buff::BuffId::Bleeding {
|
buff::BuffId::Bleeding {
|
||||||
strength: attack.base_damage as f32,
|
strength: attack.base_damage as f32,
|
||||||
duration: Some(Duration::from_secs(10)),
|
duration: Some(Duration::from_secs(30)),
|
||||||
},
|
},
|
||||||
vec![buff::BuffCategoryId::Physical, buff::BuffCategoryId::Debuff],
|
vec![buff::BuffCategoryId::Physical, buff::BuffCategoryId::Debuff],
|
||||||
buff::BuffSource::Character { by: *uid },
|
buff::BuffSource::Character { by: *uid },
|
||||||
)),
|
)),
|
||||||
});
|
});
|
||||||
|
server_emitter.emit(ServerEvent::Buff {
|
||||||
|
uid: *uid_b,
|
||||||
|
buff_change: buff::BuffChange::Add(buff::Buff::new(
|
||||||
|
buff::BuffId::Regeneration {
|
||||||
|
strength: 100.0,
|
||||||
|
duration: Some(Duration::from_secs(60)),
|
||||||
|
},
|
||||||
|
vec![buff::BuffCategoryId::Physical, buff::BuffCategoryId::Buff],
|
||||||
|
buff::BuffSource::Character { by: *uid },
|
||||||
|
)),
|
||||||
|
});
|
||||||
|
server_emitter.emit(ServerEvent::Buff {
|
||||||
|
uid: *uid_b,
|
||||||
|
buff_change: buff::BuffChange::Add(buff::Buff::new(
|
||||||
|
buff::BuffId::Cursed { duration: None },
|
||||||
|
vec![buff::BuffCategoryId::Physical, buff::BuffCategoryId::Debuff],
|
||||||
|
buff::BuffSource::Character { by: *uid },
|
||||||
|
)),
|
||||||
|
});
|
||||||
attack.hit_count += 1;
|
attack.hit_count += 1;
|
||||||
}
|
}
|
||||||
if attack.knockback != 0.0 && damage.healthchange != 0.0 {
|
if attack.knockback != 0.0 && damage.healthchange != 0.0 {
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
use crate::{
|
use crate::{
|
||||||
comp::{
|
comp::{
|
||||||
slot::{EquipSlot, Slot},
|
slot::{EquipSlot, Slot},
|
||||||
CharacterState, ControlEvent, Controller, InventoryManip,
|
BuffChange, CharacterState, ControlEvent, Controller, InventoryManip,
|
||||||
},
|
},
|
||||||
event::{EventBus, LocalEvent, ServerEvent},
|
event::{EventBus, LocalEvent, ServerEvent},
|
||||||
metrics::SysMetrics,
|
metrics::SysMetrics,
|
||||||
@ -51,7 +51,7 @@ impl<'a> System<'a> for Sys {
|
|||||||
span!(_guard, "run", "controller::Sys::run");
|
span!(_guard, "run", "controller::Sys::run");
|
||||||
let mut server_emitter = server_bus.emitter();
|
let mut server_emitter = server_bus.emitter();
|
||||||
|
|
||||||
for (entity, _uid, controller, character_state) in
|
for (entity, uid, controller, character_state) in
|
||||||
(&entities, &uids, &mut controllers, &mut character_states).join()
|
(&entities, &uids, &mut controllers, &mut character_states).join()
|
||||||
{
|
{
|
||||||
let mut inputs = &mut controller.inputs;
|
let mut inputs = &mut controller.inputs;
|
||||||
@ -83,6 +83,12 @@ impl<'a> System<'a> for Sys {
|
|||||||
server_emitter.emit(ServerEvent::Mount(entity, mountee_entity));
|
server_emitter.emit(ServerEvent::Mount(entity, mountee_entity));
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
ControlEvent::RemoveBuff(buff_id) => {
|
||||||
|
server_emitter.emit(ServerEvent::Buff {
|
||||||
|
uid: *uid,
|
||||||
|
buff_change: BuffChange::RemoveById(buff_id),
|
||||||
|
});
|
||||||
|
},
|
||||||
ControlEvent::Unmount => server_emitter.emit(ServerEvent::Unmount(entity)),
|
ControlEvent::Unmount => server_emitter.emit(ServerEvent::Unmount(entity)),
|
||||||
ControlEvent::EnableLantern => {
|
ControlEvent::EnableLantern => {
|
||||||
server_emitter.emit(ServerEvent::EnableLantern(entity))
|
server_emitter.emit(ServerEvent::EnableLantern(entity))
|
||||||
|
@ -715,6 +715,7 @@ pub fn handle_buff(server: &mut Server, uid: Uid, buff_change: buff::BuffChange)
|
|||||||
add_buff_effects(new_buff.clone(), stats.get_mut(entity));
|
add_buff_effects(new_buff.clone(), stats.get_mut(entity));
|
||||||
buffs.active_buffs.push(new_buff);
|
buffs.active_buffs.push(new_buff);
|
||||||
} else {
|
} else {
|
||||||
|
let mut duplicate_existed = false;
|
||||||
for i in 0..buffs.active_buffs.len() {
|
for i in 0..buffs.active_buffs.len() {
|
||||||
let active_buff = &buffs.active_buffs[i];
|
let active_buff = &buffs.active_buffs[i];
|
||||||
// Checks if new buff has the same id as an already active buff. If it
|
// Checks if new buff has the same id as an already active buff. If it
|
||||||
@ -724,6 +725,7 @@ pub fn handle_buff(server: &mut Server, uid: Uid, buff_change: buff::BuffChange)
|
|||||||
// inactive buffs and add new buff to active
|
// inactive buffs and add new buff to active
|
||||||
// buffs.
|
// buffs.
|
||||||
if discriminant(&active_buff.id) == discriminant(&new_buff.id) {
|
if discriminant(&active_buff.id) == discriminant(&new_buff.id) {
|
||||||
|
duplicate_existed = true;
|
||||||
if determine_replace_active_buff(
|
if determine_replace_active_buff(
|
||||||
active_buff.clone(),
|
active_buff.clone(),
|
||||||
new_buff.clone(),
|
new_buff.clone(),
|
||||||
@ -731,15 +733,22 @@ pub fn handle_buff(server: &mut Server, uid: Uid, buff_change: buff::BuffChange)
|
|||||||
active_buff_indices_for_removal.push(i);
|
active_buff_indices_for_removal.push(i);
|
||||||
add_buff_effects(new_buff.clone(), stats.get_mut(entity));
|
add_buff_effects(new_buff.clone(), stats.get_mut(entity));
|
||||||
buffs.active_buffs.push(new_buff.clone());
|
buffs.active_buffs.push(new_buff.clone());
|
||||||
} else {
|
} else if let Some(active_dur) = active_buff.time {
|
||||||
|
if let Some(new_dur) = new_buff.time {
|
||||||
|
if new_dur > active_dur {
|
||||||
buffs.inactive_buffs.push(new_buff.clone());
|
buffs.inactive_buffs.push(new_buff.clone());
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
buffs.inactive_buffs.push(new_buff.clone());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if !duplicate_existed {
|
||||||
add_buff_effects(new_buff.clone(), stats.get_mut(entity));
|
add_buff_effects(new_buff.clone(), stats.get_mut(entity));
|
||||||
buffs.active_buffs.push(new_buff.clone());
|
buffs.active_buffs.push(new_buff.clone());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
},
|
},
|
||||||
BuffChange::RemoveByIndex(active_indices, inactive_indices) => {
|
BuffChange::RemoveByIndex(active_indices, inactive_indices) => {
|
||||||
active_buff_indices_for_removal = active_indices;
|
active_buff_indices_for_removal = active_indices;
|
||||||
@ -871,7 +880,7 @@ fn determine_replace_active_buff(active_buff: buff::Buff, new_buff: buff::Buff)
|
|||||||
duration: _,
|
duration: _,
|
||||||
} = active_buff.id
|
} = active_buff.id
|
||||||
{
|
{
|
||||||
new_strength > active_strength
|
new_strength >= active_strength
|
||||||
} else {
|
} else {
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
@ -885,7 +894,7 @@ fn determine_replace_active_buff(active_buff: buff::Buff, new_buff: buff::Buff)
|
|||||||
duration: _,
|
duration: _,
|
||||||
} = active_buff.id
|
} = active_buff.id
|
||||||
{
|
{
|
||||||
new_strength > active_strength
|
new_strength >= active_strength
|
||||||
} else {
|
} else {
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
|
@ -1,20 +1,23 @@
|
|||||||
use super::{
|
use super::{
|
||||||
img_ids::{Imgs, ImgsRot},
|
img_ids::{Imgs, ImgsRot},
|
||||||
TEXT_COLOR,
|
BUFF_COLOR, DEBUFF_COLOR, TEXT_COLOR,
|
||||||
};
|
};
|
||||||
use crate::{
|
use crate::{
|
||||||
|
hud::{get_buff_info, BuffPosition},
|
||||||
i18n::VoxygenLocalization,
|
i18n::VoxygenLocalization,
|
||||||
ui::{fonts::ConrodVoxygenFonts, ImageFrame, Tooltip, TooltipManager, Tooltipable},
|
ui::{fonts::ConrodVoxygenFonts, ImageFrame, Tooltip, TooltipManager, Tooltipable},
|
||||||
GlobalState,
|
GlobalState,
|
||||||
};
|
};
|
||||||
use client::Client;
|
|
||||||
use common::comp::{self, Buffs};
|
use crate::hud::BuffInfo;
|
||||||
|
use common::comp::{BuffId, Buffs};
|
||||||
use conrod_core::{
|
use conrod_core::{
|
||||||
color,
|
color,
|
||||||
widget::{self, Button, Image, Rectangle, Text},
|
widget::{self, Button, Image, Rectangle},
|
||||||
widget_ids, Color, Colorable, Positionable, Sizeable, Widget, WidgetCommon,
|
widget_ids, Color, Positionable, Sizeable, Widget, WidgetCommon,
|
||||||
};
|
};
|
||||||
use inline_tweak::*;
|
use inline_tweak::*;
|
||||||
|
use std::time::Duration;
|
||||||
widget_ids! {
|
widget_ids! {
|
||||||
struct Ids {
|
struct Ids {
|
||||||
align,
|
align,
|
||||||
@ -22,51 +25,49 @@ widget_ids! {
|
|||||||
debuffs_align,
|
debuffs_align,
|
||||||
buff_test,
|
buff_test,
|
||||||
debuff_test,
|
debuff_test,
|
||||||
|
buffs[],
|
||||||
|
buff_timers[],
|
||||||
|
debuffs[],
|
||||||
|
debuff_timers[],
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct BuffInfo {
|
|
||||||
id: comp::BuffId,
|
|
||||||
is_buff: bool,
|
|
||||||
dur: f32,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(WidgetCommon)]
|
#[derive(WidgetCommon)]
|
||||||
pub struct BuffsBar<'a> {
|
pub struct BuffsBar<'a> {
|
||||||
client: &'a Client,
|
|
||||||
imgs: &'a Imgs,
|
imgs: &'a Imgs,
|
||||||
fonts: &'a ConrodVoxygenFonts,
|
fonts: &'a ConrodVoxygenFonts,
|
||||||
#[conrod(common_builder)]
|
#[conrod(common_builder)]
|
||||||
common: widget::CommonBuilder,
|
common: widget::CommonBuilder,
|
||||||
global_state: &'a GlobalState,
|
|
||||||
rot_imgs: &'a ImgsRot,
|
rot_imgs: &'a ImgsRot,
|
||||||
tooltip_manager: &'a mut TooltipManager,
|
tooltip_manager: &'a mut TooltipManager,
|
||||||
localized_strings: &'a std::sync::Arc<VoxygenLocalization>,
|
localized_strings: &'a std::sync::Arc<VoxygenLocalization>,
|
||||||
buffs: &'a Buffs,
|
buffs: &'a Buffs,
|
||||||
|
pulse: f32,
|
||||||
|
global_state: &'a GlobalState,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> BuffsBar<'a> {
|
impl<'a> BuffsBar<'a> {
|
||||||
#[allow(clippy::too_many_arguments)] // TODO: Pending review in #587
|
#[allow(clippy::too_many_arguments)] // TODO: Pending review in #587
|
||||||
pub fn new(
|
pub fn new(
|
||||||
client: &'a Client,
|
|
||||||
imgs: &'a Imgs,
|
imgs: &'a Imgs,
|
||||||
fonts: &'a ConrodVoxygenFonts,
|
fonts: &'a ConrodVoxygenFonts,
|
||||||
global_state: &'a GlobalState,
|
|
||||||
rot_imgs: &'a ImgsRot,
|
rot_imgs: &'a ImgsRot,
|
||||||
tooltip_manager: &'a mut TooltipManager,
|
tooltip_manager: &'a mut TooltipManager,
|
||||||
localized_strings: &'a std::sync::Arc<VoxygenLocalization>,
|
localized_strings: &'a std::sync::Arc<VoxygenLocalization>,
|
||||||
buffs: &'a Buffs,
|
buffs: &'a Buffs,
|
||||||
|
pulse: f32,
|
||||||
|
global_state: &'a GlobalState,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
Self {
|
Self {
|
||||||
client,
|
|
||||||
imgs,
|
imgs,
|
||||||
fonts,
|
fonts,
|
||||||
common: widget::CommonBuilder::default(),
|
common: widget::CommonBuilder::default(),
|
||||||
global_state,
|
|
||||||
rot_imgs,
|
rot_imgs,
|
||||||
tooltip_manager,
|
tooltip_manager,
|
||||||
localized_strings,
|
localized_strings,
|
||||||
buffs,
|
buffs,
|
||||||
|
pulse,
|
||||||
|
global_state,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -75,8 +76,12 @@ pub struct State {
|
|||||||
ids: Ids,
|
ids: Ids,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub enum Event {
|
||||||
|
RemoveBuff(BuffId),
|
||||||
|
}
|
||||||
|
|
||||||
impl<'a> Widget for BuffsBar<'a> {
|
impl<'a> Widget for BuffsBar<'a> {
|
||||||
type Event = ();
|
type Event = Vec<Event>;
|
||||||
type State = State;
|
type State = State;
|
||||||
type Style = ();
|
type Style = ();
|
||||||
|
|
||||||
@ -91,7 +96,11 @@ impl<'a> Widget for BuffsBar<'a> {
|
|||||||
|
|
||||||
fn update(self, args: widget::UpdateArgs<Self>) -> Self::Event {
|
fn update(self, args: widget::UpdateArgs<Self>) -> Self::Event {
|
||||||
let widget::UpdateArgs { state, ui, .. } = args;
|
let widget::UpdateArgs { state, ui, .. } = args;
|
||||||
|
let mut event = Vec::new();
|
||||||
let localized_strings = self.localized_strings;
|
let localized_strings = self.localized_strings;
|
||||||
|
let buffs = self.buffs;
|
||||||
|
let buff_ani = ((self.pulse * 4.0/* speed factor */).cos() * 0.5 + 0.8) + 0.5; //Animation timer
|
||||||
|
let buff_position = self.global_state.settings.gameplay.buff_position;
|
||||||
let buffs_tooltip = Tooltip::new({
|
let buffs_tooltip = Tooltip::new({
|
||||||
// Edge images [t, b, r, l]
|
// Edge images [t, b, r, l]
|
||||||
// Corner images [tr, tl, br, bl]
|
// Corner images [tr, tl, br, bl]
|
||||||
@ -109,6 +118,7 @@ impl<'a> Widget for BuffsBar<'a> {
|
|||||||
.desc_font_size(self.fonts.cyri.scale(12))
|
.desc_font_size(self.fonts.cyri.scale(12))
|
||||||
.font_id(self.fonts.cyri.conrod_id)
|
.font_id(self.fonts.cyri.conrod_id)
|
||||||
.desc_text_color(TEXT_COLOR);
|
.desc_text_color(TEXT_COLOR);
|
||||||
|
if let BuffPosition::Bar = buff_position {
|
||||||
// Alignment
|
// Alignment
|
||||||
Rectangle::fill_with([484.0, 100.0], color::TRANSPARENT)
|
Rectangle::fill_with([484.0, 100.0], color::TRANSPARENT)
|
||||||
.mid_bottom_with_margin_on(ui.window, tweak!(92.0))
|
.mid_bottom_with_margin_on(ui.window, tweak!(92.0))
|
||||||
@ -119,25 +129,219 @@ impl<'a> Widget for BuffsBar<'a> {
|
|||||||
Rectangle::fill_with([484.0 / 2.0, 90.0], color::TRANSPARENT)
|
Rectangle::fill_with([484.0 / 2.0, 90.0], color::TRANSPARENT)
|
||||||
.bottom_right_with_margins_on(state.ids.align, 0.0, 0.0)
|
.bottom_right_with_margins_on(state.ids.align, 0.0, 0.0)
|
||||||
.set(state.ids.buffs_align, ui);
|
.set(state.ids.buffs_align, ui);
|
||||||
// Test Widgets
|
|
||||||
Image::new(self.imgs.debuff_skull_0)
|
|
||||||
.w_h(20.0, 20.0)
|
|
||||||
.bottom_right_with_margins_on(state.ids.debuffs_align, 0.0, 1.0)
|
|
||||||
.set(state.ids.debuff_test, ui);
|
|
||||||
Image::new(self.imgs.buff_plus_0)
|
|
||||||
.w_h(20.0, 20.0)
|
|
||||||
.bottom_left_with_margins_on(state.ids.buffs_align, 0.0, 1.0)
|
|
||||||
.set(state.ids.buff_test, ui);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn get_buff_info(buff: comp::Buff) -> BuffInfo {
|
// Buffs and Debuffs
|
||||||
BuffInfo {
|
// Create two vecs to display buffs and debuffs separately
|
||||||
id: buff.id,
|
let mut buffs_vec = Vec::<BuffInfo>::new();
|
||||||
is_buff: buff
|
let mut debuffs_vec = Vec::<BuffInfo>::new();
|
||||||
.cat_ids
|
for buff in buffs.active_buffs.clone() {
|
||||||
.iter()
|
let info = get_buff_info(buff);
|
||||||
.any(|cat| *cat == comp::BuffCategoryId::Buff),
|
if info.is_buff {
|
||||||
dur: buff.time.map(|dur| dur.as_secs_f32()).unwrap_or(100.0),
|
buffs_vec.push(info);
|
||||||
|
} else {
|
||||||
|
debuffs_vec.push(info);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if state.ids.buffs.len() < buffs_vec.len() {
|
||||||
|
state.update(|state| {
|
||||||
|
state
|
||||||
|
.ids
|
||||||
|
.buffs
|
||||||
|
.resize(buffs_vec.len(), &mut ui.widget_id_generator())
|
||||||
|
});
|
||||||
|
};
|
||||||
|
if state.ids.debuffs.len() < debuffs_vec.len() {
|
||||||
|
state.update(|state| {
|
||||||
|
state
|
||||||
|
.ids
|
||||||
|
.debuffs
|
||||||
|
.resize(debuffs_vec.len(), &mut ui.widget_id_generator())
|
||||||
|
});
|
||||||
|
};
|
||||||
|
if state.ids.buff_timers.len() < buffs_vec.len() {
|
||||||
|
state.update(|state| {
|
||||||
|
state
|
||||||
|
.ids
|
||||||
|
.buff_timers
|
||||||
|
.resize(buffs_vec.len(), &mut ui.widget_id_generator())
|
||||||
|
});
|
||||||
|
};
|
||||||
|
if state.ids.debuff_timers.len() < debuffs_vec.len() {
|
||||||
|
state.update(|state| {
|
||||||
|
state
|
||||||
|
.ids
|
||||||
|
.debuff_timers
|
||||||
|
.resize(debuffs_vec.len(), &mut ui.widget_id_generator())
|
||||||
|
});
|
||||||
|
};
|
||||||
|
let pulsating_col = Color::Rgba(1.0, 1.0, 1.0, buff_ani);
|
||||||
|
let norm_col = Color::Rgba(1.0, 1.0, 1.0, 1.0);
|
||||||
|
// Create Buff Widgets
|
||||||
|
for (i, buff) in buffs_vec.iter().enumerate() {
|
||||||
|
if i < 22 {
|
||||||
|
// Limit displayed buffs
|
||||||
|
let max_duration = match buff.id {
|
||||||
|
BuffId::Regeneration { duration, .. } => duration.unwrap().as_secs_f32(),
|
||||||
|
_ => 10.0,
|
||||||
|
};
|
||||||
|
let current_duration = buff.dur;
|
||||||
|
let duration_percentage = (current_duration / max_duration * 1000.0) as u32; // Percentage to determine which frame of the timer overlay is displayed
|
||||||
|
let buff_img = match buff.id {
|
||||||
|
BuffId::Regeneration { .. } => self.imgs.buff_plus_0,
|
||||||
|
_ => self.imgs.missing_icon,
|
||||||
|
};
|
||||||
|
let buff_widget = Image::new(buff_img).w_h(20.0, 20.0);
|
||||||
|
// Sort buffs into rows of 11 slots
|
||||||
|
let x = i % 11;
|
||||||
|
let y = i / 11;
|
||||||
|
let buff_widget = buff_widget.bottom_left_with_margins_on(
|
||||||
|
state.ids.buffs_align,
|
||||||
|
0.0 + y as f64 * (21.0),
|
||||||
|
0.0 + x as f64 * (21.0),
|
||||||
|
);
|
||||||
|
buff_widget
|
||||||
|
.color(if current_duration < 10.0 {
|
||||||
|
Some(pulsating_col)
|
||||||
|
} else {
|
||||||
|
Some(norm_col)
|
||||||
|
})
|
||||||
|
.set(state.ids.buffs[i], ui);
|
||||||
|
// Create Buff tooltip
|
||||||
|
let title = match buff.id {
|
||||||
|
BuffId::Regeneration { .. } => {
|
||||||
|
*&localized_strings.get("buff.title.heal_test")
|
||||||
|
},
|
||||||
|
_ => *&localized_strings.get("buff.title.missing"),
|
||||||
|
};
|
||||||
|
let remaining_time = if current_duration == 10e6 as f32 {
|
||||||
|
"Permanent".to_string()
|
||||||
|
} else {
|
||||||
|
format!("Remaining: {:.0}s", current_duration)
|
||||||
|
};
|
||||||
|
let click_to_remove = format!("<{}>", &localized_strings.get("buff.remove"));
|
||||||
|
let desc_txt = match buff.id {
|
||||||
|
BuffId::Regeneration { .. } => {
|
||||||
|
*&localized_strings.get("buff.desc.heal_test")
|
||||||
|
},
|
||||||
|
_ => *&localized_strings.get("buff.desc.missing"),
|
||||||
|
};
|
||||||
|
let desc = format!("{}\n\n{}\n\n{}", desc_txt, remaining_time, click_to_remove);
|
||||||
|
// Timer overlay
|
||||||
|
if Button::image(match duration_percentage as u64 {
|
||||||
|
875..=1000 => self.imgs.nothing, // 8/8
|
||||||
|
750..=874 => self.imgs.buff_0, // 7/8
|
||||||
|
625..=749 => self.imgs.buff_1, // 6/8
|
||||||
|
500..=624 => self.imgs.buff_2, // 5/8
|
||||||
|
375..=499 => self.imgs.buff_3, // 4/8
|
||||||
|
250..=374 => self.imgs.buff_4, //3/8
|
||||||
|
125..=249 => self.imgs.buff_5, // 2/8
|
||||||
|
0..=124 => self.imgs.buff_6, // 1/8
|
||||||
|
_ => self.imgs.nothing,
|
||||||
|
})
|
||||||
|
.w_h(20.0, 20.0)
|
||||||
|
.middle_of(state.ids.buffs[i])
|
||||||
|
.with_tooltip(
|
||||||
|
self.tooltip_manager,
|
||||||
|
title,
|
||||||
|
&desc,
|
||||||
|
&buffs_tooltip,
|
||||||
|
BUFF_COLOR,
|
||||||
|
)
|
||||||
|
.set(state.ids.buff_timers[i], ui)
|
||||||
|
.was_clicked()
|
||||||
|
{
|
||||||
|
event.push(Event::RemoveBuff(buff.id));
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
|
// Create Debuff Widgets
|
||||||
|
for (i, debuff) in debuffs_vec.iter().enumerate() {
|
||||||
|
if i < 22 {
|
||||||
|
// Limit displayed buffs
|
||||||
|
|
||||||
|
let max_duration = match debuff.id {
|
||||||
|
BuffId::Bleeding { duration, .. } => {
|
||||||
|
duration.unwrap_or(Duration::from_secs(60)).as_secs_f32()
|
||||||
|
},
|
||||||
|
BuffId::Cursed { duration, .. } => {
|
||||||
|
duration.unwrap_or(Duration::from_secs(60)).as_secs_f32()
|
||||||
|
},
|
||||||
|
|
||||||
|
_ => 10.0,
|
||||||
|
};
|
||||||
|
let current_duration = debuff.dur;
|
||||||
|
let duration_percentage = current_duration / max_duration * 1000.0; // Percentage to determine which frame of the timer overlay is displayed
|
||||||
|
let debuff_img = match debuff.id {
|
||||||
|
BuffId::Bleeding { .. } => self.imgs.debuff_bleed_0,
|
||||||
|
BuffId::Cursed { .. } => self.imgs.debuff_skull_0,
|
||||||
|
_ => self.imgs.missing_icon,
|
||||||
|
};
|
||||||
|
let debuff_widget = Image::new(debuff_img).w_h(20.0, 20.0);
|
||||||
|
// Sort buffs into rows of 11 slots
|
||||||
|
let x = i % 11;
|
||||||
|
let y = i / 11;
|
||||||
|
let debuff_widget = debuff_widget.bottom_right_with_margins_on(
|
||||||
|
state.ids.debuffs_align,
|
||||||
|
0.0 + y as f64 * (21.0),
|
||||||
|
0.0 + x as f64 * (21.0),
|
||||||
|
);
|
||||||
|
|
||||||
|
debuff_widget
|
||||||
|
.color(if current_duration < 10.0 {
|
||||||
|
Some(pulsating_col)
|
||||||
|
} else {
|
||||||
|
Some(norm_col)
|
||||||
|
})
|
||||||
|
.set(state.ids.debuffs[i], ui);
|
||||||
|
// Create Debuff tooltip
|
||||||
|
let title = match debuff.id {
|
||||||
|
BuffId::Bleeding { .. } => {
|
||||||
|
*&localized_strings.get("debuff.title.bleed_test")
|
||||||
|
},
|
||||||
|
_ => *&localized_strings.get("buff.title.missing"),
|
||||||
|
};
|
||||||
|
let remaining_time = if current_duration == 10e6 as f32 {
|
||||||
|
"Permanent".to_string()
|
||||||
|
} else {
|
||||||
|
format!("Remaining: {:.0}s", current_duration)
|
||||||
|
};
|
||||||
|
let desc_txt = match debuff.id {
|
||||||
|
BuffId::Bleeding { .. } => {
|
||||||
|
*&localized_strings.get("debuff.desc.bleed_test")
|
||||||
|
},
|
||||||
|
_ => *&localized_strings.get("debuff.desc.missing"),
|
||||||
|
};
|
||||||
|
let desc = format!("{}\n\n{}", desc_txt, remaining_time);
|
||||||
|
Image::new(match duration_percentage as u64 {
|
||||||
|
875..=1000 => self.imgs.nothing, // 8/8
|
||||||
|
750..=874 => self.imgs.buff_0, // 7/8
|
||||||
|
625..=749 => self.imgs.buff_1, // 6/8
|
||||||
|
500..=624 => self.imgs.buff_2, // 5/8
|
||||||
|
375..=499 => self.imgs.buff_3, // 4/8
|
||||||
|
250..=374 => self.imgs.buff_4, //3/8
|
||||||
|
125..=249 => self.imgs.buff_5, // 2/8
|
||||||
|
0..=124 => self.imgs.buff_6, // 1/8
|
||||||
|
_ => self.imgs.nothing,
|
||||||
|
})
|
||||||
|
.w_h(20.0, 20.0)
|
||||||
|
.middle_of(state.ids.debuffs[i])
|
||||||
|
.with_tooltip(
|
||||||
|
self.tooltip_manager,
|
||||||
|
title,
|
||||||
|
&desc,
|
||||||
|
&buffs_tooltip,
|
||||||
|
DEBUFF_COLOR,
|
||||||
|
)
|
||||||
|
.set(state.ids.debuff_timers[i], ui);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if let BuffPosition::Map = buff_position {
|
||||||
|
// Alignment
|
||||||
|
Rectangle::fill_with([tweak!(300.0), tweak!(280.0)], color::RED)
|
||||||
|
.top_right_with_margins_on(ui.window, tweak!(5.0), tweak!(270.0))
|
||||||
|
.set(state.ids.align, ui);
|
||||||
|
}
|
||||||
|
event
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,15 +1,20 @@
|
|||||||
use super::{
|
use super::{
|
||||||
img_ids::Imgs, Show, BLACK, ERROR_COLOR, GROUP_COLOR, HP_COLOR, KILL_COLOR, LOW_HP_COLOR,
|
img_ids::{Imgs, ImgsRot},
|
||||||
STAMINA_COLOR, TEXT_COLOR, TEXT_COLOR_GREY, UI_HIGHLIGHT_0, UI_MAIN,
|
Show, BLACK, BUFF_COLOR, DEBUFF_COLOR, ERROR_COLOR, GROUP_COLOR, HP_COLOR, KILL_COLOR,
|
||||||
|
LOW_HP_COLOR, STAMINA_COLOR, TEXT_COLOR, TEXT_COLOR_GREY, UI_HIGHLIGHT_0, UI_MAIN,
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
i18n::VoxygenLocalization, settings::Settings, ui::fonts::ConrodVoxygenFonts,
|
hud::{get_buff_info, BuffInfo},
|
||||||
window::GameInput, GlobalState,
|
i18n::VoxygenLocalization,
|
||||||
|
settings::Settings,
|
||||||
|
ui::{fonts::ConrodVoxygenFonts, ImageFrame, Tooltip, TooltipManager, Tooltipable},
|
||||||
|
window::GameInput,
|
||||||
|
GlobalState,
|
||||||
};
|
};
|
||||||
use client::{self, Client};
|
use client::{self, Client};
|
||||||
use common::{
|
use common::{
|
||||||
comp::{group::Role, Stats},
|
comp::{group::Role, BuffId, Buffs, Stats},
|
||||||
sync::{Uid, WorldSyncExt},
|
sync::{Uid, WorldSyncExt},
|
||||||
};
|
};
|
||||||
use conrod_core::{
|
use conrod_core::{
|
||||||
@ -18,8 +23,8 @@ use conrod_core::{
|
|||||||
widget::{self, Button, Image, Rectangle, Scrollbar, Text},
|
widget::{self, Button, Image, Rectangle, Scrollbar, Text},
|
||||||
widget_ids, Color, Colorable, Labelable, Positionable, Sizeable, Widget, WidgetCommon,
|
widget_ids, Color, Colorable, Labelable, Positionable, Sizeable, Widget, WidgetCommon,
|
||||||
};
|
};
|
||||||
|
use inline_tweak::*;
|
||||||
use specs::{saveload::MarkerAllocator, WorldExt};
|
use specs::{saveload::MarkerAllocator, WorldExt};
|
||||||
|
|
||||||
widget_ids! {
|
widget_ids! {
|
||||||
pub struct Ids {
|
pub struct Ids {
|
||||||
group_button,
|
group_button,
|
||||||
@ -44,6 +49,8 @@ widget_ids! {
|
|||||||
member_panels_txt[],
|
member_panels_txt[],
|
||||||
member_health[],
|
member_health[],
|
||||||
member_stam[],
|
member_stam[],
|
||||||
|
buffs[],
|
||||||
|
buff_timers[],
|
||||||
dead_txt[],
|
dead_txt[],
|
||||||
health_txt[],
|
health_txt[],
|
||||||
timeout_bg,
|
timeout_bg,
|
||||||
@ -63,10 +70,13 @@ pub struct Group<'a> {
|
|||||||
client: &'a Client,
|
client: &'a Client,
|
||||||
settings: &'a Settings,
|
settings: &'a Settings,
|
||||||
imgs: &'a Imgs,
|
imgs: &'a Imgs,
|
||||||
|
rot_imgs: &'a ImgsRot,
|
||||||
fonts: &'a ConrodVoxygenFonts,
|
fonts: &'a ConrodVoxygenFonts,
|
||||||
localized_strings: &'a std::sync::Arc<VoxygenLocalization>,
|
localized_strings: &'a std::sync::Arc<VoxygenLocalization>,
|
||||||
pulse: f32,
|
pulse: f32,
|
||||||
global_state: &'a GlobalState,
|
global_state: &'a GlobalState,
|
||||||
|
buffs: &'a Buffs,
|
||||||
|
tooltip_manager: &'a mut TooltipManager,
|
||||||
|
|
||||||
#[conrod(common_builder)]
|
#[conrod(common_builder)]
|
||||||
common: widget::CommonBuilder,
|
common: widget::CommonBuilder,
|
||||||
@ -79,20 +89,26 @@ impl<'a> Group<'a> {
|
|||||||
client: &'a Client,
|
client: &'a Client,
|
||||||
settings: &'a Settings,
|
settings: &'a Settings,
|
||||||
imgs: &'a Imgs,
|
imgs: &'a Imgs,
|
||||||
|
rot_imgs: &'a ImgsRot,
|
||||||
fonts: &'a ConrodVoxygenFonts,
|
fonts: &'a ConrodVoxygenFonts,
|
||||||
localized_strings: &'a std::sync::Arc<VoxygenLocalization>,
|
localized_strings: &'a std::sync::Arc<VoxygenLocalization>,
|
||||||
pulse: f32,
|
pulse: f32,
|
||||||
global_state: &'a GlobalState,
|
global_state: &'a GlobalState,
|
||||||
|
buffs: &'a Buffs,
|
||||||
|
tooltip_manager: &'a mut TooltipManager,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
Self {
|
Self {
|
||||||
show,
|
show,
|
||||||
client,
|
client,
|
||||||
settings,
|
settings,
|
||||||
imgs,
|
imgs,
|
||||||
|
rot_imgs,
|
||||||
fonts,
|
fonts,
|
||||||
localized_strings,
|
localized_strings,
|
||||||
pulse,
|
pulse,
|
||||||
global_state,
|
global_state,
|
||||||
|
buffs,
|
||||||
|
tooltip_manager,
|
||||||
common: widget::CommonBuilder::default(),
|
common: widget::CommonBuilder::default(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -127,8 +143,27 @@ impl<'a> Widget for Group<'a> {
|
|||||||
#[allow(clippy::blocks_in_if_conditions)] // TODO: Pending review in #587
|
#[allow(clippy::blocks_in_if_conditions)] // TODO: Pending review in #587
|
||||||
fn update(self, args: widget::UpdateArgs<Self>) -> Self::Event {
|
fn update(self, args: widget::UpdateArgs<Self>) -> Self::Event {
|
||||||
let widget::UpdateArgs { state, ui, .. } = args;
|
let widget::UpdateArgs { state, ui, .. } = args;
|
||||||
|
|
||||||
let mut events = Vec::new();
|
let mut events = Vec::new();
|
||||||
|
let localized_strings = self.localized_strings;
|
||||||
|
//let buffs = self.buffs;
|
||||||
|
let buff_ani = ((self.pulse * 4.0/* speed factor */).cos() * 0.5 + 0.8) + 0.5; //Animation timer
|
||||||
|
let buffs_tooltip = Tooltip::new({
|
||||||
|
// Edge images [t, b, r, l]
|
||||||
|
// Corner images [tr, tl, br, bl]
|
||||||
|
let edge = &self.rot_imgs.tt_side;
|
||||||
|
let corner = &self.rot_imgs.tt_corner;
|
||||||
|
ImageFrame::new(
|
||||||
|
[edge.cw180, edge.none, edge.cw270, edge.cw90],
|
||||||
|
[corner.none, corner.cw270, corner.cw90, corner.cw180],
|
||||||
|
Color::Rgba(0.08, 0.07, 0.04, 1.0),
|
||||||
|
5.0,
|
||||||
|
)
|
||||||
|
})
|
||||||
|
.title_font_size(self.fonts.cyri.scale(15))
|
||||||
|
.parent(ui.window)
|
||||||
|
.desc_font_size(self.fonts.cyri.scale(12))
|
||||||
|
.font_id(self.fonts.cyri.conrod_id)
|
||||||
|
.desc_text_color(TEXT_COLOR);
|
||||||
|
|
||||||
// Don't show pets
|
// Don't show pets
|
||||||
let group_members = self
|
let group_members = self
|
||||||
@ -293,6 +328,7 @@ impl<'a> Widget for Group<'a> {
|
|||||||
let client_state = self.client.state();
|
let client_state = self.client.state();
|
||||||
let stats = client_state.ecs().read_storage::<common::comp::Stats>();
|
let stats = client_state.ecs().read_storage::<common::comp::Stats>();
|
||||||
let energy = client_state.ecs().read_storage::<common::comp::Energy>();
|
let energy = client_state.ecs().read_storage::<common::comp::Energy>();
|
||||||
|
let buffs = client_state.ecs().read_storage::<common::comp::Buffs>();
|
||||||
let uid_allocator = client_state
|
let uid_allocator = client_state
|
||||||
.ecs()
|
.ecs()
|
||||||
.read_resource::<common::sync::UidAllocator>();
|
.read_resource::<common::sync::UidAllocator>();
|
||||||
@ -302,6 +338,8 @@ impl<'a> Widget for Group<'a> {
|
|||||||
let entity = uid_allocator.retrieve_entity_internal(uid.into());
|
let entity = uid_allocator.retrieve_entity_internal(uid.into());
|
||||||
let stats = entity.and_then(|entity| stats.get(entity));
|
let stats = entity.and_then(|entity| stats.get(entity));
|
||||||
let energy = entity.and_then(|entity| energy.get(entity));
|
let energy = entity.and_then(|entity| energy.get(entity));
|
||||||
|
let buffs = entity.and_then(|entity| buffs.get(entity));
|
||||||
|
|
||||||
if let Some(stats) = stats {
|
if let Some(stats) = stats {
|
||||||
let char_name = stats.name.to_string();
|
let char_name = stats.name.to_string();
|
||||||
let health_perc = stats.health.current() as f64 / stats.health.maximum() as f64;
|
let health_perc = stats.health.current() as f64 / stats.health.maximum() as f64;
|
||||||
@ -317,7 +355,7 @@ impl<'a> Widget for Group<'a> {
|
|||||||
.top_left_with_margins_on(ui.window, offset, 20.0)
|
.top_left_with_margins_on(ui.window, offset, 20.0)
|
||||||
} else {
|
} else {
|
||||||
Image::new(self.imgs.member_bg)
|
Image::new(self.imgs.member_bg)
|
||||||
.down_from(state.ids.member_panels_bg[i - 1], 40.0)
|
.down_from(state.ids.member_panels_bg[i - 1], 45.0)
|
||||||
};
|
};
|
||||||
let hp_ani = (self.pulse * 4.0/* speed factor */).cos() * 0.5 + 0.8; //Animation timer
|
let hp_ani = (self.pulse * 4.0/* speed factor */).cos() * 0.5 + 0.8; //Animation timer
|
||||||
let crit_hp_color: Color = Color::Rgba(0.79, 0.19, 0.17, hp_ani);
|
let crit_hp_color: Color = Color::Rgba(0.79, 0.19, 0.17, hp_ani);
|
||||||
@ -408,16 +446,117 @@ impl<'a> Widget for Group<'a> {
|
|||||||
.top_left_with_margins_on(state.ids.member_panels_bg[i], 26.0, 2.0)
|
.top_left_with_margins_on(state.ids.member_panels_bg[i], 26.0, 2.0)
|
||||||
.set(state.ids.member_stam[i], ui);
|
.set(state.ids.member_stam[i], ui);
|
||||||
}
|
}
|
||||||
|
if let Some(buffs) = buffs {
|
||||||
|
let mut buffs_vec = Vec::<BuffInfo>::new();
|
||||||
|
for buff in buffs.active_buffs.clone() {
|
||||||
|
let info = get_buff_info(buff);
|
||||||
|
buffs_vec.push(info);
|
||||||
|
}
|
||||||
|
state.update(|state| {
|
||||||
|
state.ids.buffs.resize(
|
||||||
|
state.ids.buffs.len() + buffs_vec.len(),
|
||||||
|
&mut ui.widget_id_generator(),
|
||||||
|
)
|
||||||
|
});
|
||||||
|
state.update(|state| {
|
||||||
|
state.ids.buff_timers.resize(
|
||||||
|
state.ids.buff_timers.len() + buffs_vec.len(),
|
||||||
|
&mut ui.widget_id_generator(),
|
||||||
|
)
|
||||||
|
});
|
||||||
|
// Create Buff Widgets
|
||||||
|
for (x, buff) in buffs_vec.iter().enumerate() {
|
||||||
|
if x < 11 {
|
||||||
|
// Limit displayed buffs
|
||||||
|
let max_duration = match buff.id {
|
||||||
|
BuffId::Regeneration { duration, .. } => {
|
||||||
|
duration.unwrap().as_secs_f32()
|
||||||
|
},
|
||||||
|
_ => 10.0,
|
||||||
|
};
|
||||||
|
let pulsating_col = Color::Rgba(1.0, 1.0, 1.0, buff_ani);
|
||||||
|
let norm_col = Color::Rgba(1.0, 1.0, 1.0, 1.0);
|
||||||
|
let current_duration = buff.dur;
|
||||||
|
let duration_percentage =
|
||||||
|
(current_duration / max_duration * 1000.0) as u32; // Percentage to determine which frame of the timer overlay is displayed
|
||||||
|
let buff_img = match buff.id {
|
||||||
|
BuffId::Regeneration { .. } => self.imgs.buff_plus_0,
|
||||||
|
BuffId::Bleeding { .. } => self.imgs.debuff_bleed_0,
|
||||||
|
BuffId::Cursed { .. } => self.imgs.debuff_skull_0,
|
||||||
|
};
|
||||||
|
let buff_widget = Image::new(buff_img).w_h(20.0, 20.0);
|
||||||
|
let buff_widget = if x == 0 {
|
||||||
|
buff_widget.bottom_left_with_margins_on(
|
||||||
|
state.ids.member_panels_frame[i],
|
||||||
|
-21.0,
|
||||||
|
1.0,
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
buff_widget.right_from(state.ids.buffs[state.ids.buffs.len() - buffs_vec.len() + x - 1/*x - 1*/], 1.0)
|
||||||
|
};
|
||||||
|
buff_widget
|
||||||
|
.color(if current_duration < 10.0 {
|
||||||
|
Some(pulsating_col)
|
||||||
|
} else {
|
||||||
|
Some(norm_col)
|
||||||
|
})
|
||||||
|
.set(state.ids.buffs[state.ids.buffs.len() - buffs_vec.len() + x/*x*/], ui);
|
||||||
|
// Create Buff tooltip
|
||||||
|
let title = match buff.id {
|
||||||
|
BuffId::Regeneration { .. } => {
|
||||||
|
*&localized_strings.get("buff.title.heal_test")
|
||||||
|
},
|
||||||
|
BuffId::Bleeding { .. } => {
|
||||||
|
*&localized_strings.get("debuff.title.bleed_test")
|
||||||
|
},
|
||||||
|
_ => *&localized_strings.get("buff.title.missing"),
|
||||||
|
};
|
||||||
|
let remaining_time = if current_duration == 10e6 as f32 {
|
||||||
|
"Permanent".to_string()
|
||||||
|
} else {
|
||||||
|
format!("Remaining: {:.0}s", current_duration)
|
||||||
|
};
|
||||||
|
let desc_txt = match buff.id {
|
||||||
|
BuffId::Regeneration { .. } => {
|
||||||
|
*&localized_strings.get("buff.desc.heal_test")
|
||||||
|
},
|
||||||
|
BuffId::Bleeding { .. } => {
|
||||||
|
*&localized_strings.get("debuff.desc.bleed_test")
|
||||||
|
},
|
||||||
|
_ => *&localized_strings.get("buff.desc.missing"),
|
||||||
|
};
|
||||||
|
let desc = format!("{}\n\n{}", desc_txt, remaining_time);
|
||||||
|
Image::new(match duration_percentage as u64 {
|
||||||
|
875..=1000 => self.imgs.nothing, // 8/8
|
||||||
|
750..=874 => self.imgs.buff_0, // 7/8
|
||||||
|
625..=749 => self.imgs.buff_1, // 6/8
|
||||||
|
500..=624 => self.imgs.buff_2, // 5/8
|
||||||
|
375..=499 => self.imgs.buff_3, // 4/8
|
||||||
|
250..=374 => self.imgs.buff_4, // 3/8
|
||||||
|
125..=249 => self.imgs.buff_5, // 2/8
|
||||||
|
0..=124 => self.imgs.buff_6, // 1/8
|
||||||
|
_ => self.imgs.nothing,
|
||||||
|
})
|
||||||
|
.w_h(20.0, 20.0)
|
||||||
|
.middle_of(state.ids.buffs[state.ids.buffs.len() - buffs_vec.len() + x/*x*/])
|
||||||
|
.with_tooltip(
|
||||||
|
self.tooltip_manager,
|
||||||
|
title,
|
||||||
|
&desc,
|
||||||
|
&buffs_tooltip,
|
||||||
|
if buff.is_buff {BUFF_COLOR} else {DEBUFF_COLOR},
|
||||||
|
)
|
||||||
|
.set(state.ids.buff_timers[state.ids.buffs.len() - buffs_vec.len() + x/*x*/], ui);
|
||||||
|
};
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
// Values N.A.
|
// Values N.A.
|
||||||
if let Some(stats) = stats {
|
|
||||||
Text::new(&stats.name.to_string())
|
Text::new(&stats.name.to_string())
|
||||||
.top_left_with_margins_on(state.ids.member_panels_frame[i], -22.0, 0.0)
|
.top_left_with_margins_on(state.ids.member_panels_frame[i], -22.0, 0.0)
|
||||||
.font_size(20)
|
.font_size(20)
|
||||||
.font_id(self.fonts.cyri.conrod_id)
|
.font_id(self.fonts.cyri.conrod_id)
|
||||||
.color(GROUP_COLOR)
|
.color(GROUP_COLOR)
|
||||||
.set(state.ids.member_panels_txt[i], ui);
|
.set(state.ids.member_panels_txt[i], ui);
|
||||||
};
|
|
||||||
let offset = if self.global_state.settings.gameplay.toggle_debug {
|
let offset = if self.global_state.settings.gameplay.toggle_debug {
|
||||||
210.0
|
210.0
|
||||||
} else {
|
} else {
|
||||||
@ -448,6 +587,7 @@ impl<'a> Widget for Group<'a> {
|
|||||||
.set(state.ids.dead_txt[i], ui);
|
.set(state.ids.dead_txt[i], ui);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if self.show.group_menu {
|
if self.show.group_menu {
|
||||||
let selected = state.selected_member;
|
let selected = state.selected_member;
|
||||||
|
@ -272,6 +272,7 @@ image_ids! {
|
|||||||
hammerleap: "voxygen.element.icons.skill_hammerleap",
|
hammerleap: "voxygen.element.icons.skill_hammerleap",
|
||||||
skill_axe_leap_slash: "voxygen.element.icons.skill_axe_leap_slash",
|
skill_axe_leap_slash: "voxygen.element.icons.skill_axe_leap_slash",
|
||||||
skill_bow_jump_burst: "voxygen.element.icons.skill_bow_jump_burst",
|
skill_bow_jump_burst: "voxygen.element.icons.skill_bow_jump_burst",
|
||||||
|
missing_icon: "voxygen.element.icons.missing_icon_grey",
|
||||||
|
|
||||||
// Buttons
|
// Buttons
|
||||||
button: "voxygen.element.buttons.button",
|
button: "voxygen.element.buttons.button",
|
||||||
@ -350,10 +351,22 @@ image_ids! {
|
|||||||
chat_world: "voxygen.element.icons.chat.world",
|
chat_world: "voxygen.element.icons.chat.world",
|
||||||
|
|
||||||
// Buffs
|
// Buffs
|
||||||
buff_plus_0: "voxygen.element.de_buffs.buff_plus_0",
|
buff_plus_0: "voxygen.element.icons.de_buffs.buff_plus_0",
|
||||||
|
|
||||||
// Debuffs
|
// Debuffs
|
||||||
debuff_skull_0: "voxygen.element.de_buffs.debuff_skull_0",
|
debuff_skull_0: "voxygen.element.icons.de_buffs.debuff_skull_0",
|
||||||
|
debuff_bleed_0: "voxygen.element.icons.de_buffs.debuff_bleed_0",
|
||||||
|
|
||||||
|
// Animation Frames
|
||||||
|
// Buff Frame
|
||||||
|
buff_0: "voxygen.element.animation.buff_frame.1",
|
||||||
|
buff_1: "voxygen.element.animation.buff_frame.2",
|
||||||
|
buff_2: "voxygen.element.animation.buff_frame.3",
|
||||||
|
buff_3: "voxygen.element.animation.buff_frame.4",
|
||||||
|
buff_4: "voxygen.element.animation.buff_frame.5",
|
||||||
|
buff_5: "voxygen.element.animation.buff_frame.6",
|
||||||
|
buff_6: "voxygen.element.animation.buff_frame.7",
|
||||||
|
buff_7: "voxygen.element.animation.buff_frame.8",
|
||||||
|
|
||||||
<BlankGraphic>
|
<BlankGraphic>
|
||||||
nothing: (),
|
nothing: (),
|
||||||
|
@ -105,7 +105,7 @@ impl<'a> Widget for MiniMap<'a> {
|
|||||||
fn update(self, args: widget::UpdateArgs<Self>) -> Self::Event {
|
fn update(self, args: widget::UpdateArgs<Self>) -> Self::Event {
|
||||||
let widget::UpdateArgs { state, ui, .. } = args;
|
let widget::UpdateArgs { state, ui, .. } = args;
|
||||||
let zoom = state.zoom;
|
let zoom = state.zoom;
|
||||||
const SCALE: f64 = 1.5;
|
const SCALE: f64 = 1.5; // TODO Make this a setting
|
||||||
if self.show.mini_map {
|
if self.show.mini_map {
|
||||||
Image::new(self.imgs.mmap_frame)
|
Image::new(self.imgs.mmap_frame)
|
||||||
.w_h(174.0 * SCALE, 190.0 * SCALE)
|
.w_h(174.0 * SCALE, 190.0 * SCALE)
|
||||||
|
@ -60,7 +60,10 @@ use client::Client;
|
|||||||
use common::{
|
use common::{
|
||||||
assets::Asset,
|
assets::Asset,
|
||||||
comp,
|
comp,
|
||||||
comp::item::{ItemDesc, Quality},
|
comp::{
|
||||||
|
item::{ItemDesc, Quality},
|
||||||
|
BuffId,
|
||||||
|
},
|
||||||
span,
|
span,
|
||||||
sync::Uid,
|
sync::Uid,
|
||||||
terrain::TerrainChunk,
|
terrain::TerrainChunk,
|
||||||
@ -97,6 +100,8 @@ const STAMINA_COLOR: Color = Color::Rgba(0.29, 0.62, 0.75, 0.9);
|
|||||||
//const TRANSPARENT: Color = Color::Rgba(0.0, 0.0, 0.0, 0.0);
|
//const TRANSPARENT: Color = Color::Rgba(0.0, 0.0, 0.0, 0.0);
|
||||||
//const FOCUS_COLOR: Color = Color::Rgba(1.0, 0.56, 0.04, 1.0);
|
//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 RAGE_COLOR: Color = Color::Rgba(0.5, 0.04, 0.13, 1.0);
|
||||||
|
const BUFF_COLOR: Color = Color::Rgba(0.06, 0.69, 0.12, 1.0);
|
||||||
|
const DEBUFF_COLOR: Color = Color::Rgba(0.79, 0.19, 0.17, 1.0);
|
||||||
|
|
||||||
// Item Quality Colors
|
// Item Quality Colors
|
||||||
const QUALITY_LOW: Color = Color::Rgba(0.41, 0.41, 0.41, 1.0); // Grey - Trash, can be sold to vendors
|
const QUALITY_LOW: Color = Color::Rgba(0.41, 0.41, 0.41, 1.0); // Grey - Trash, can be sold to vendors
|
||||||
@ -267,6 +272,13 @@ widget_ids! {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Copy)]
|
||||||
|
pub struct BuffInfo {
|
||||||
|
id: comp::BuffId,
|
||||||
|
is_buff: bool,
|
||||||
|
dur: f32,
|
||||||
|
}
|
||||||
|
|
||||||
pub struct DebugInfo {
|
pub struct DebugInfo {
|
||||||
pub tps: f64,
|
pub tps: f64,
|
||||||
pub frame_time: Duration,
|
pub frame_time: Duration,
|
||||||
@ -318,6 +330,7 @@ pub enum Event {
|
|||||||
ChatTransp(f32),
|
ChatTransp(f32),
|
||||||
ChatCharName(bool),
|
ChatCharName(bool),
|
||||||
CrosshairType(CrosshairType),
|
CrosshairType(CrosshairType),
|
||||||
|
BuffPosition(BuffPosition),
|
||||||
ToggleXpBar(XpBar),
|
ToggleXpBar(XpBar),
|
||||||
Intro(Intro),
|
Intro(Intro),
|
||||||
ToggleBarNumbers(BarNumbers),
|
ToggleBarNumbers(BarNumbers),
|
||||||
@ -351,6 +364,7 @@ pub enum Event {
|
|||||||
KickMember(common::sync::Uid),
|
KickMember(common::sync::Uid),
|
||||||
LeaveGroup,
|
LeaveGroup,
|
||||||
AssignLeader(common::sync::Uid),
|
AssignLeader(common::sync::Uid),
|
||||||
|
RemoveBuff(BuffId),
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Are these the possible layouts we want?
|
// TODO: Are these the possible layouts we want?
|
||||||
@ -391,6 +405,13 @@ pub enum ShortcutNumbers {
|
|||||||
On,
|
On,
|
||||||
Off,
|
Off,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Copy, Debug, Serialize, Deserialize)]
|
||||||
|
pub enum BuffPosition {
|
||||||
|
Bar,
|
||||||
|
Map,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Clone, Copy, Debug, Serialize, Deserialize)]
|
#[derive(Clone, Copy, Debug, Serialize, Deserialize)]
|
||||||
pub enum PressBehavior {
|
pub enum PressBehavior {
|
||||||
Toggle = 0,
|
Toggle = 0,
|
||||||
@ -725,6 +746,7 @@ impl Hud {
|
|||||||
let ecs = client.state().ecs();
|
let ecs = client.state().ecs();
|
||||||
let pos = ecs.read_storage::<comp::Pos>();
|
let pos = ecs.read_storage::<comp::Pos>();
|
||||||
let stats = ecs.read_storage::<comp::Stats>();
|
let stats = ecs.read_storage::<comp::Stats>();
|
||||||
|
let buffs = ecs.read_storage::<comp::Buffs>();
|
||||||
let energy = ecs.read_storage::<comp::Energy>();
|
let energy = ecs.read_storage::<comp::Energy>();
|
||||||
let hp_floater_lists = ecs.read_storage::<vcomp::HpFloaterList>();
|
let hp_floater_lists = ecs.read_storage::<vcomp::HpFloaterList>();
|
||||||
let uids = ecs.read_storage::<common::sync::Uid>();
|
let uids = ecs.read_storage::<common::sync::Uid>();
|
||||||
@ -1123,11 +1145,12 @@ impl Hud {
|
|||||||
let speech_bubbles = &self.speech_bubbles;
|
let speech_bubbles = &self.speech_bubbles;
|
||||||
|
|
||||||
// Render overhead name tags and health bars
|
// Render overhead name tags and health bars
|
||||||
for (pos, info, bubble, stats, height_offset, hpfl, in_group) in (
|
for (pos, info, bubble, stats, buffs, height_offset, hpfl, in_group) in (
|
||||||
&entities,
|
&entities,
|
||||||
&pos,
|
&pos,
|
||||||
interpolated.maybe(),
|
interpolated.maybe(),
|
||||||
&stats,
|
&stats,
|
||||||
|
&buffs,
|
||||||
energy.maybe(),
|
energy.maybe(),
|
||||||
scales.maybe(),
|
scales.maybe(),
|
||||||
&bodies,
|
&bodies,
|
||||||
@ -1141,7 +1164,7 @@ impl Hud {
|
|||||||
entity != me && !stats.is_dead
|
entity != me && !stats.is_dead
|
||||||
})
|
})
|
||||||
.filter_map(
|
.filter_map(
|
||||||
|(entity, pos, interpolated, stats, energy, scale, body, hpfl, uid)| {
|
|(entity, pos, interpolated, stats, buffs, energy, scale, body, hpfl, uid)| {
|
||||||
// Use interpolated position if available
|
// Use interpolated position if available
|
||||||
let pos = interpolated.map_or(pos.0, |i| i.pos);
|
let pos = interpolated.map_or(pos.0, |i| i.pos);
|
||||||
let in_group = client.group_members().contains_key(uid);
|
let in_group = client.group_members().contains_key(uid);
|
||||||
@ -1171,6 +1194,7 @@ impl Hud {
|
|||||||
let info = display_overhead_info.then(|| overhead::Info {
|
let info = display_overhead_info.then(|| overhead::Info {
|
||||||
name: &stats.name,
|
name: &stats.name,
|
||||||
stats,
|
stats,
|
||||||
|
buffs,
|
||||||
energy,
|
energy,
|
||||||
});
|
});
|
||||||
let bubble = if dist_sqr < SPEECH_BUBBLE_RANGE.powi(2) {
|
let bubble = if dist_sqr < SPEECH_BUBBLE_RANGE.powi(2) {
|
||||||
@ -1185,6 +1209,7 @@ impl Hud {
|
|||||||
info,
|
info,
|
||||||
bubble,
|
bubble,
|
||||||
stats,
|
stats,
|
||||||
|
buffs,
|
||||||
body.height() * scale.map_or(1.0, |s| s.0) + 0.5,
|
body.height() * scale.map_or(1.0, |s| s.0) + 0.5,
|
||||||
hpfl,
|
hpfl,
|
||||||
in_group,
|
in_group,
|
||||||
@ -1760,22 +1785,48 @@ impl Hud {
|
|||||||
|
|
||||||
// Buffs and Debuffs
|
// Buffs and Debuffs
|
||||||
if let Some(player_buffs) = buffs.get(client.entity()) {
|
if let Some(player_buffs) = buffs.get(client.entity()) {
|
||||||
match BuffsBar::new(
|
for event in BuffsBar::new(
|
||||||
client,
|
|
||||||
&self.imgs,
|
&self.imgs,
|
||||||
&self.fonts,
|
&self.fonts,
|
||||||
global_state,
|
|
||||||
&self.rot_imgs,
|
&self.rot_imgs,
|
||||||
tooltip_manager,
|
tooltip_manager,
|
||||||
&self.voxygen_i18n,
|
&self.voxygen_i18n,
|
||||||
&player_buffs,
|
&player_buffs,
|
||||||
|
self.pulse,
|
||||||
|
&global_state,
|
||||||
)
|
)
|
||||||
.set(self.ids.buffs, ui_widgets)
|
.set(self.ids.buffs, ui_widgets)
|
||||||
{
|
{
|
||||||
_ => {},
|
match event {
|
||||||
|
buffs::Event::RemoveBuff(buff_id) => events.push(Event::RemoveBuff(buff_id)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Group Window
|
||||||
|
let buffs = buffs.get(client.entity()).unwrap();
|
||||||
|
for event in Group::new(
|
||||||
|
&mut self.show,
|
||||||
|
client,
|
||||||
|
&global_state.settings,
|
||||||
|
&self.imgs,
|
||||||
|
&self.rot_imgs,
|
||||||
|
&self.fonts,
|
||||||
|
&self.voxygen_i18n,
|
||||||
|
self.pulse,
|
||||||
|
&global_state,
|
||||||
|
&buffs,
|
||||||
|
tooltip_manager,
|
||||||
|
)
|
||||||
|
.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)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Popup (waypoint saved and similar notifications)
|
// Popup (waypoint saved and similar notifications)
|
||||||
Popup::new(
|
Popup::new(
|
||||||
&self.voxygen_i18n,
|
&self.voxygen_i18n,
|
||||||
@ -1850,8 +1901,8 @@ impl Hud {
|
|||||||
Some(stats),
|
Some(stats),
|
||||||
Some(loadout),
|
Some(loadout),
|
||||||
Some(energy),
|
Some(energy),
|
||||||
Some(character_state),
|
Some(_character_state),
|
||||||
Some(controller),
|
Some(_controller),
|
||||||
Some(inventory),
|
Some(inventory),
|
||||||
) = (
|
) = (
|
||||||
stats.get(entity),
|
stats.get(entity),
|
||||||
@ -2018,6 +2069,9 @@ impl Hud {
|
|||||||
settings_window::Event::ToggleZoomInvert(zoom_inverted) => {
|
settings_window::Event::ToggleZoomInvert(zoom_inverted) => {
|
||||||
events.push(Event::ToggleZoomInvert(zoom_inverted));
|
events.push(Event::ToggleZoomInvert(zoom_inverted));
|
||||||
},
|
},
|
||||||
|
settings_window::Event::BuffPosition(buff_position) => {
|
||||||
|
events.push(Event::BuffPosition(buff_position));
|
||||||
|
},
|
||||||
settings_window::Event::ToggleMouseYInvert(mouse_y_inverted) => {
|
settings_window::Event::ToggleMouseYInvert(mouse_y_inverted) => {
|
||||||
events.push(Event::ToggleMouseYInvert(mouse_y_inverted));
|
events.push(Event::ToggleMouseYInvert(mouse_y_inverted));
|
||||||
},
|
},
|
||||||
@ -2142,27 +2196,6 @@ impl Hud {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Group Window
|
|
||||||
for event in Group::new(
|
|
||||||
&mut self.show,
|
|
||||||
client,
|
|
||||||
&global_state.settings,
|
|
||||||
&self.imgs,
|
|
||||||
&self.fonts,
|
|
||||||
&self.voxygen_i18n,
|
|
||||||
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)),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Spellbook
|
// Spellbook
|
||||||
if self.show.spell {
|
if self.show.spell {
|
||||||
@ -2694,3 +2727,17 @@ pub fn get_quality_col<I: ItemDesc>(item: &I) -> Color {
|
|||||||
Quality::Debug => QUALITY_DEBUG,
|
Quality::Debug => QUALITY_DEBUG,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// Get info about applied buffs
|
||||||
|
fn get_buff_info(buff: comp::Buff) -> BuffInfo {
|
||||||
|
BuffInfo {
|
||||||
|
id: buff.id,
|
||||||
|
is_buff: buff
|
||||||
|
.cat_ids
|
||||||
|
.iter()
|
||||||
|
.any(|cat| *cat == comp::BuffCategoryId::Buff),
|
||||||
|
dur: buff
|
||||||
|
.time
|
||||||
|
.map(|dur| dur.as_secs_f32())
|
||||||
|
.unwrap_or(10e6 as f32),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -3,16 +3,19 @@ use super::{
|
|||||||
REGION_COLOR, SAY_COLOR, STAMINA_COLOR, TELL_COLOR, TEXT_BG, TEXT_COLOR,
|
REGION_COLOR, SAY_COLOR, STAMINA_COLOR, TELL_COLOR, TEXT_BG, TEXT_COLOR,
|
||||||
};
|
};
|
||||||
use crate::{
|
use crate::{
|
||||||
|
hud::{get_buff_info, BuffInfo},
|
||||||
i18n::VoxygenLocalization,
|
i18n::VoxygenLocalization,
|
||||||
settings::GameplaySettings,
|
settings::GameplaySettings,
|
||||||
ui::{fonts::ConrodVoxygenFonts, Ingameable},
|
ui::{fonts::ConrodVoxygenFonts, Ingameable},
|
||||||
};
|
};
|
||||||
use common::comp::{Energy, SpeechBubble, SpeechBubbleType, Stats};
|
use common::comp::{BuffId, Buffs, Energy, SpeechBubble, SpeechBubbleType, Stats};
|
||||||
use conrod_core::{
|
use conrod_core::{
|
||||||
|
color,
|
||||||
position::Align,
|
position::Align,
|
||||||
widget::{self, Image, Rectangle, Text},
|
widget::{self, Image, Rectangle, Text},
|
||||||
widget_ids, Color, Colorable, Positionable, Sizeable, Widget, WidgetCommon,
|
widget_ids, Color, Colorable, Positionable, Sizeable, Widget, WidgetCommon,
|
||||||
};
|
};
|
||||||
|
use inline_tweak::*;
|
||||||
const MAX_BUBBLE_WIDTH: f64 = 250.0;
|
const MAX_BUBBLE_WIDTH: f64 = 250.0;
|
||||||
|
|
||||||
widget_ids! {
|
widget_ids! {
|
||||||
@ -44,13 +47,24 @@ widget_ids! {
|
|||||||
health_txt,
|
health_txt,
|
||||||
mana_bar,
|
mana_bar,
|
||||||
health_bar_fg,
|
health_bar_fg,
|
||||||
|
|
||||||
|
// Buffs
|
||||||
|
buffs_align,
|
||||||
|
buffs[],
|
||||||
|
buff_timers[],
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*pub struct BuffInfo {
|
||||||
|
id: comp::BuffId,
|
||||||
|
dur: f32,
|
||||||
|
}*/
|
||||||
|
|
||||||
#[derive(Clone, Copy)]
|
#[derive(Clone, Copy)]
|
||||||
pub struct Info<'a> {
|
pub struct Info<'a> {
|
||||||
pub name: &'a str,
|
pub name: &'a str,
|
||||||
pub stats: &'a Stats,
|
pub stats: &'a Stats,
|
||||||
|
pub buffs: &'a Buffs,
|
||||||
pub energy: Option<&'a Energy>,
|
pub energy: Option<&'a Energy>,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -119,13 +133,17 @@ impl<'a> Ingameable for Overhead<'a> {
|
|||||||
// - 1 for HP text
|
// - 1 for HP text
|
||||||
// - If there's mana
|
// - If there's mana
|
||||||
// - 1 Rect::new for mana
|
// - 1 Rect::new for mana
|
||||||
//
|
// If there are Buffs
|
||||||
|
// - 1 Alignment Rectangle
|
||||||
|
// - 10 + 10 Buffs and Timer Overlays
|
||||||
// If there's a speech bubble
|
// If there's a speech bubble
|
||||||
// - 2 Text::new for speech bubble
|
// - 2 Text::new for speech bubble
|
||||||
// - 1 Image::new for icon
|
// - 1 Image::new for icon
|
||||||
// - 10 Image::new for speech bubble (9-slice + tail)
|
// - 10 Image::new for speech bubble (9-slice + tail)
|
||||||
self.info.map_or(0, |info| {
|
self.info.map_or(0, |info| {
|
||||||
2 + if show_healthbar(info.stats) {
|
2 + 1
|
||||||
|
+ info.buffs.active_buffs.len().min(10) * 2
|
||||||
|
+ if show_healthbar(info.stats) {
|
||||||
5 + if info.energy.is_some() { 1 } else { 0 }
|
5 + if info.energy.is_some() { 1 } else { 0 }
|
||||||
} else {
|
} else {
|
||||||
0
|
0
|
||||||
@ -155,6 +173,7 @@ impl<'a> Widget for Overhead<'a> {
|
|||||||
if let Some(Info {
|
if let Some(Info {
|
||||||
name,
|
name,
|
||||||
stats,
|
stats,
|
||||||
|
buffs,
|
||||||
energy,
|
energy,
|
||||||
}) = self.info
|
}) = self.info
|
||||||
{
|
{
|
||||||
@ -172,6 +191,11 @@ impl<'a> Widget for Overhead<'a> {
|
|||||||
} else {
|
} else {
|
||||||
MANA_BAR_Y + 32.0
|
MANA_BAR_Y + 32.0
|
||||||
};
|
};
|
||||||
|
let mut buffs_vec = Vec::<BuffInfo>::new();
|
||||||
|
for buff in buffs.active_buffs.clone() {
|
||||||
|
let info = get_buff_info(buff);
|
||||||
|
buffs_vec.push(info);
|
||||||
|
}
|
||||||
let font_size = if hp_percentage.abs() > 99.9 { 24 } else { 20 };
|
let font_size = if hp_percentage.abs() > 99.9 { 24 } else { 20 };
|
||||||
// Show K for numbers above 10^3 and truncate them
|
// Show K for numbers above 10^3 and truncate them
|
||||||
// Show M for numbers above 10^6 and truncate them
|
// Show M for numbers above 10^6 and truncate them
|
||||||
@ -185,6 +209,79 @@ impl<'a> Widget for Overhead<'a> {
|
|||||||
1000..=999999 => format!("{:.0}K", (health_max / 1000.0).max(1.0)),
|
1000..=999999 => format!("{:.0}K", (health_max / 1000.0).max(1.0)),
|
||||||
_ => format!("{:.0}M", (health_max as f64 / 1.0e6).max(1.0)),
|
_ => format!("{:.0}M", (health_max as f64 / 1.0e6).max(1.0)),
|
||||||
};
|
};
|
||||||
|
// Buffs
|
||||||
|
// Alignment
|
||||||
|
Rectangle::fill_with([tweak!(168.0), tweak!(100.0)], color::TRANSPARENT)
|
||||||
|
.x_y(-1.0, name_y + tweak!(60.0))
|
||||||
|
.parent(id)
|
||||||
|
.set(state.ids.buffs_align, ui);
|
||||||
|
if state.ids.buffs.len() < buffs_vec.len() {
|
||||||
|
state.update(|state| {
|
||||||
|
state
|
||||||
|
.ids
|
||||||
|
.buffs
|
||||||
|
.resize(buffs_vec.len(), &mut ui.widget_id_generator())
|
||||||
|
});
|
||||||
|
};
|
||||||
|
if state.ids.buff_timers.len() < buffs_vec.len() {
|
||||||
|
state.update(|state| {
|
||||||
|
state
|
||||||
|
.ids
|
||||||
|
.buff_timers
|
||||||
|
.resize(buffs_vec.len(), &mut ui.widget_id_generator())
|
||||||
|
});
|
||||||
|
};
|
||||||
|
let buff_ani = ((self.pulse * 4.0).cos() * 0.5 + 0.8) + 0.5; //Animation timer
|
||||||
|
let pulsating_col = Color::Rgba(1.0, 1.0, 1.0, buff_ani);
|
||||||
|
let norm_col = Color::Rgba(1.0, 1.0, 1.0, 1.0);
|
||||||
|
// Create Buff Widgets
|
||||||
|
for (i, buff) in buffs_vec.iter().enumerate() {
|
||||||
|
if i < 11 && self.bubble.is_none() {
|
||||||
|
// Limit displayed buffs
|
||||||
|
let max_duration = match buff.id {
|
||||||
|
BuffId::Regeneration { duration, .. } => duration.unwrap().as_secs_f32(),
|
||||||
|
_ => 10.0,
|
||||||
|
};
|
||||||
|
let current_duration = buff.dur;
|
||||||
|
let duration_percentage = (current_duration / max_duration * 1000.0) as u32; // Percentage to determine which frame of the timer overlay is displayed
|
||||||
|
let buff_img = match buff.id {
|
||||||
|
BuffId::Regeneration { .. } => self.imgs.buff_plus_0,
|
||||||
|
BuffId::Bleeding { .. } => self.imgs.debuff_bleed_0,
|
||||||
|
BuffId::Cursed { .. } => self.imgs.debuff_skull_0,
|
||||||
|
};
|
||||||
|
let buff_widget = Image::new(buff_img).w_h(20.0, 20.0);
|
||||||
|
// Sort buffs into rows of 5 slots
|
||||||
|
let x = i % 5;
|
||||||
|
let y = i / 5;
|
||||||
|
let buff_widget = buff_widget.bottom_left_with_margins_on(
|
||||||
|
state.ids.buffs_align,
|
||||||
|
0.0 + y as f64 * (21.0),
|
||||||
|
0.0 + x as f64 * (21.0),
|
||||||
|
);
|
||||||
|
buff_widget
|
||||||
|
.color(if current_duration < 10.0 {
|
||||||
|
Some(pulsating_col)
|
||||||
|
} else {
|
||||||
|
Some(norm_col)
|
||||||
|
})
|
||||||
|
.set(state.ids.buffs[i], ui);
|
||||||
|
|
||||||
|
Image::new(match duration_percentage as u64 {
|
||||||
|
875..=1000 => self.imgs.nothing, // 8/8
|
||||||
|
750..=874 => self.imgs.buff_0, // 7/8
|
||||||
|
625..=749 => self.imgs.buff_1, // 6/8
|
||||||
|
500..=624 => self.imgs.buff_2, // 5/8
|
||||||
|
375..=499 => self.imgs.buff_3, // 4/8
|
||||||
|
250..=374 => self.imgs.buff_4, //3/8
|
||||||
|
125..=249 => self.imgs.buff_5, // 2/8
|
||||||
|
0..=124 => self.imgs.buff_6, // 1/8
|
||||||
|
_ => self.imgs.nothing,
|
||||||
|
})
|
||||||
|
.w_h(20.0, 20.0)
|
||||||
|
.middle_of(state.ids.buffs[i])
|
||||||
|
.set(state.ids.buff_timers[i], ui);
|
||||||
|
};
|
||||||
|
}
|
||||||
// Name
|
// Name
|
||||||
Text::new(name)
|
Text::new(name)
|
||||||
.font_id(self.fonts.cyri.conrod_id)
|
.font_id(self.fonts.cyri.conrod_id)
|
||||||
|
@ -4,6 +4,7 @@ use super::{
|
|||||||
TEXT_BIND_CONFLICT_COLOR, TEXT_COLOR, UI_HIGHLIGHT_0, UI_MAIN,
|
TEXT_BIND_CONFLICT_COLOR, TEXT_COLOR, UI_HIGHLIGHT_0, UI_MAIN,
|
||||||
};
|
};
|
||||||
use crate::{
|
use crate::{
|
||||||
|
hud::BuffPosition,
|
||||||
i18n::{list_localizations, LanguageMetadata, VoxygenLocalization},
|
i18n::{list_localizations, LanguageMetadata, VoxygenLocalization},
|
||||||
render::{AaMode, CloudMode, FluidMode, LightingMode, RenderMode, ShadowMapMode, ShadowMode},
|
render::{AaMode, CloudMode, FluidMode, LightingMode, RenderMode, ShadowMapMode, ShadowMode},
|
||||||
ui::{fonts::ConrodVoxygenFonts, ImageSlider, ScaleMode, ToggleButton},
|
ui::{fonts::ConrodVoxygenFonts, ImageSlider, ScaleMode, ToggleButton},
|
||||||
@ -159,6 +160,7 @@ widget_ids! {
|
|||||||
sfx_volume_text,
|
sfx_volume_text,
|
||||||
audio_device_list,
|
audio_device_list,
|
||||||
audio_device_text,
|
audio_device_text,
|
||||||
|
//
|
||||||
hotbar_title,
|
hotbar_title,
|
||||||
bar_numbers_title,
|
bar_numbers_title,
|
||||||
show_bar_numbers_none_button,
|
show_bar_numbers_none_button,
|
||||||
@ -167,18 +169,20 @@ widget_ids! {
|
|||||||
show_bar_numbers_values_text,
|
show_bar_numbers_values_text,
|
||||||
show_bar_numbers_percentage_button,
|
show_bar_numbers_percentage_button,
|
||||||
show_bar_numbers_percentage_text,
|
show_bar_numbers_percentage_text,
|
||||||
|
//
|
||||||
show_shortcuts_button,
|
show_shortcuts_button,
|
||||||
show_shortcuts_text,
|
show_shortcuts_text,
|
||||||
show_xpbar_button,
|
buff_pos_bar_button,
|
||||||
show_xpbar_text,
|
buff_pos_bar_text,
|
||||||
show_bars_button,
|
buff_pos_map_button,
|
||||||
show_bars_text,
|
buff_pos_map_text,
|
||||||
placeholder,
|
//
|
||||||
chat_transp_title,
|
chat_transp_title,
|
||||||
chat_transp_text,
|
chat_transp_text,
|
||||||
chat_transp_slider,
|
chat_transp_slider,
|
||||||
chat_char_name_text,
|
chat_char_name_text,
|
||||||
chat_char_name_button,
|
chat_char_name_button,
|
||||||
|
//
|
||||||
sct_title,
|
sct_title,
|
||||||
sct_show_text,
|
sct_show_text,
|
||||||
sct_show_radio,
|
sct_show_radio,
|
||||||
@ -195,6 +199,7 @@ widget_ids! {
|
|||||||
sct_num_dur_text,
|
sct_num_dur_text,
|
||||||
sct_num_dur_slider,
|
sct_num_dur_slider,
|
||||||
sct_num_dur_value,
|
sct_num_dur_value,
|
||||||
|
//
|
||||||
speech_bubble_text,
|
speech_bubble_text,
|
||||||
speech_bubble_dark_mode_text,
|
speech_bubble_dark_mode_text,
|
||||||
speech_bubble_dark_mode_button,
|
speech_bubble_dark_mode_button,
|
||||||
@ -261,6 +266,7 @@ pub enum Event {
|
|||||||
ToggleTips(bool),
|
ToggleTips(bool),
|
||||||
ToggleBarNumbers(BarNumbers),
|
ToggleBarNumbers(BarNumbers),
|
||||||
ToggleShortcutNumbers(ShortcutNumbers),
|
ToggleShortcutNumbers(ShortcutNumbers),
|
||||||
|
BuffPosition(BuffPosition),
|
||||||
ChangeTab(SettingsTab),
|
ChangeTab(SettingsTab),
|
||||||
Close,
|
Close,
|
||||||
AdjustMousePan(u32),
|
AdjustMousePan(u32),
|
||||||
@ -829,11 +835,61 @@ impl<'a> Widget for SettingsWindow<'a> {
|
|||||||
.graphics_for(state.ids.show_shortcuts_button)
|
.graphics_for(state.ids.show_shortcuts_button)
|
||||||
.color(TEXT_COLOR)
|
.color(TEXT_COLOR)
|
||||||
.set(state.ids.show_shortcuts_text, ui);
|
.set(state.ids.show_shortcuts_text, ui);
|
||||||
|
// Buff Position
|
||||||
Rectangle::fill_with([60.0 * 4.0, 1.0 * 4.0], color::TRANSPARENT)
|
// Buffs above skills
|
||||||
.down_from(state.ids.show_shortcuts_text, 30.0)
|
if Button::image(match self.global_state.settings.gameplay.buff_position {
|
||||||
.set(state.ids.placeholder, ui);
|
BuffPosition::Bar => self.imgs.checkbox_checked,
|
||||||
|
BuffPosition::Map => self.imgs.checkbox,
|
||||||
|
})
|
||||||
|
.w_h(18.0, 18.0)
|
||||||
|
.hover_image(match self.global_state.settings.gameplay.buff_position {
|
||||||
|
BuffPosition::Bar => self.imgs.checkbox_checked_mo,
|
||||||
|
BuffPosition::Map => self.imgs.checkbox_mo,
|
||||||
|
})
|
||||||
|
.press_image(match self.global_state.settings.gameplay.buff_position {
|
||||||
|
BuffPosition::Bar => self.imgs.checkbox_checked,
|
||||||
|
BuffPosition::Map => self.imgs.checkbox_press,
|
||||||
|
})
|
||||||
|
.down_from(state.ids.show_shortcuts_button, 8.0)
|
||||||
|
.set(state.ids.buff_pos_bar_button, ui)
|
||||||
|
.was_clicked()
|
||||||
|
{
|
||||||
|
events.push(Event::BuffPosition(BuffPosition::Bar))
|
||||||
|
}
|
||||||
|
Text::new(&self.localized_strings.get("hud.settings.buffs_skillbar"))
|
||||||
|
.right_from(state.ids.buff_pos_bar_button, 10.0)
|
||||||
|
.font_size(self.fonts.cyri.scale(14))
|
||||||
|
.font_id(self.fonts.cyri.conrod_id)
|
||||||
|
.graphics_for(state.ids.show_shortcuts_button)
|
||||||
|
.color(TEXT_COLOR)
|
||||||
|
.set(state.ids.buff_pos_bar_text, ui);
|
||||||
|
// Buffs left from minimap
|
||||||
|
if Button::image(match self.global_state.settings.gameplay.buff_position {
|
||||||
|
BuffPosition::Map => self.imgs.checkbox_checked,
|
||||||
|
BuffPosition::Bar => self.imgs.checkbox,
|
||||||
|
})
|
||||||
|
.w_h(18.0, 18.0)
|
||||||
|
.hover_image(match self.global_state.settings.gameplay.buff_position {
|
||||||
|
BuffPosition::Map => self.imgs.checkbox_checked_mo,
|
||||||
|
BuffPosition::Bar => self.imgs.checkbox_mo,
|
||||||
|
})
|
||||||
|
.press_image(match self.global_state.settings.gameplay.buff_position {
|
||||||
|
BuffPosition::Map => self.imgs.checkbox_checked,
|
||||||
|
BuffPosition::Bar => self.imgs.checkbox_press,
|
||||||
|
})
|
||||||
|
.down_from(state.ids.buff_pos_bar_button, 8.0)
|
||||||
|
.set(state.ids.buff_pos_map_button, ui)
|
||||||
|
.was_clicked()
|
||||||
|
{
|
||||||
|
events.push(Event::BuffPosition(BuffPosition::Map))
|
||||||
|
}
|
||||||
|
Text::new(&self.localized_strings.get("hud.settings.buffs_mmap"))
|
||||||
|
.right_from(state.ids.buff_pos_map_button, 10.0)
|
||||||
|
.font_size(self.fonts.cyri.scale(14))
|
||||||
|
.font_id(self.fonts.cyri.conrod_id)
|
||||||
|
.graphics_for(state.ids.show_shortcuts_button)
|
||||||
|
.color(TEXT_COLOR)
|
||||||
|
.set(state.ids.buff_pos_map_text, ui);
|
||||||
// Content Right Side
|
// Content Right Side
|
||||||
|
|
||||||
/*Scrolling Combat text
|
/*Scrolling Combat text
|
||||||
|
@ -894,6 +894,10 @@ impl PlayState for SessionState {
|
|||||||
global_state.settings.gameplay.shortcut_numbers = shortcut_numbers;
|
global_state.settings.gameplay.shortcut_numbers = shortcut_numbers;
|
||||||
global_state.settings.save_to_file_warn();
|
global_state.settings.save_to_file_warn();
|
||||||
},
|
},
|
||||||
|
HudEvent::BuffPosition(buff_position) => {
|
||||||
|
global_state.settings.gameplay.buff_position = buff_position;
|
||||||
|
global_state.settings.save_to_file_warn();
|
||||||
|
},
|
||||||
HudEvent::UiScale(scale_change) => {
|
HudEvent::UiScale(scale_change) => {
|
||||||
global_state.settings.gameplay.ui_scale =
|
global_state.settings.gameplay.ui_scale =
|
||||||
self.hud.scale_change(scale_change);
|
self.hud.scale_change(scale_change);
|
||||||
@ -921,6 +925,10 @@ impl PlayState for SessionState {
|
|||||||
global_state.settings.graphics.max_fps = fps;
|
global_state.settings.graphics.max_fps = fps;
|
||||||
global_state.settings.save_to_file_warn();
|
global_state.settings.save_to_file_warn();
|
||||||
},
|
},
|
||||||
|
HudEvent::RemoveBuff(buff_id) => {
|
||||||
|
let mut client = self.client.borrow_mut();
|
||||||
|
client.remove_buff(buff_id);
|
||||||
|
},
|
||||||
HudEvent::UseSlot(x) => self.client.borrow_mut().use_slot(x),
|
HudEvent::UseSlot(x) => self.client.borrow_mut().use_slot(x),
|
||||||
HudEvent::SwapSlots(a, b) => self.client.borrow_mut().swap_slots(a, b),
|
HudEvent::SwapSlots(a, b) => self.client.borrow_mut().swap_slots(a, b),
|
||||||
HudEvent::DropSlot(x) => {
|
HudEvent::DropSlot(x) => {
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
use crate::{
|
use crate::{
|
||||||
hud::{BarNumbers, CrosshairType, Intro, PressBehavior, ShortcutNumbers, XpBar},
|
hud::{BarNumbers, BuffPosition, CrosshairType, Intro, PressBehavior, ShortcutNumbers, XpBar},
|
||||||
i18n,
|
i18n,
|
||||||
render::RenderMode,
|
render::RenderMode,
|
||||||
ui::ScaleMode,
|
ui::ScaleMode,
|
||||||
@ -507,6 +507,7 @@ pub struct GameplaySettings {
|
|||||||
pub intro_show: Intro,
|
pub intro_show: Intro,
|
||||||
pub xp_bar: XpBar,
|
pub xp_bar: XpBar,
|
||||||
pub shortcut_numbers: ShortcutNumbers,
|
pub shortcut_numbers: ShortcutNumbers,
|
||||||
|
pub buff_position: BuffPosition,
|
||||||
pub bar_numbers: BarNumbers,
|
pub bar_numbers: BarNumbers,
|
||||||
pub ui_scale: ScaleMode,
|
pub ui_scale: ScaleMode,
|
||||||
pub free_look_behavior: PressBehavior,
|
pub free_look_behavior: PressBehavior,
|
||||||
@ -537,6 +538,7 @@ impl Default for GameplaySettings {
|
|||||||
intro_show: Intro::Show,
|
intro_show: Intro::Show,
|
||||||
xp_bar: XpBar::Always,
|
xp_bar: XpBar::Always,
|
||||||
shortcut_numbers: ShortcutNumbers::On,
|
shortcut_numbers: ShortcutNumbers::On,
|
||||||
|
buff_position: BuffPosition::Bar,
|
||||||
bar_numbers: BarNumbers::Values,
|
bar_numbers: BarNumbers::Values,
|
||||||
ui_scale: ScaleMode::RelativeToWindow([1920.0, 1080.0].into()),
|
ui_scale: ScaleMode::RelativeToWindow([1920.0, 1080.0].into()),
|
||||||
free_look_behavior: PressBehavior::Toggle,
|
free_look_behavior: PressBehavior::Toggle,
|
||||||
|
Reference in New Issue
Block a user