2020-07-25 23:21:15 +00:00
|
|
|
use super::{
|
2020-08-05 11:29:42 +00:00
|
|
|
img_ids::Imgs, Show, BLACK, ERROR_COLOR, GROUP_COLOR, HP_COLOR, KILL_COLOR, LOW_HP_COLOR,
|
|
|
|
MANA_COLOR, TEXT_COLOR, TEXT_COLOR_GREY, UI_HIGHLIGHT_0, UI_MAIN,
|
2020-07-25 23:21:15 +00:00
|
|
|
};
|
2020-07-12 00:39:50 +00:00
|
|
|
|
2020-07-19 21:49:18 +00:00
|
|
|
use crate::{
|
2020-08-04 07:22:59 +00:00
|
|
|
i18n::VoxygenLocalization, settings::Settings, ui::fonts::ConrodVoxygenFonts,
|
|
|
|
window::GameInput, GlobalState,
|
2020-07-19 21:49:18 +00:00
|
|
|
};
|
2020-07-12 00:39:50 +00:00
|
|
|
use client::{self, Client};
|
|
|
|
use common::{
|
2020-07-19 21:49:18 +00:00
|
|
|
comp::{group::Role, Stats},
|
2020-07-12 00:39:50 +00:00
|
|
|
sync::{Uid, WorldSyncExt},
|
|
|
|
};
|
|
|
|
use conrod_core::{
|
|
|
|
color,
|
2020-07-19 21:49:18 +00:00
|
|
|
position::{Place, Relative},
|
2020-07-12 00:39:50 +00:00
|
|
|
widget::{self, Button, Image, Rectangle, Scrollbar, Text},
|
2020-07-25 23:21:15 +00:00
|
|
|
widget_ids, Color, Colorable, Labelable, Positionable, Sizeable, Widget, WidgetCommon,
|
2020-07-12 00:39:50 +00:00
|
|
|
};
|
2020-07-25 23:21:15 +00:00
|
|
|
use specs::{saveload::MarkerAllocator, WorldExt};
|
2020-07-12 00:39:50 +00:00
|
|
|
|
|
|
|
widget_ids! {
|
|
|
|
pub struct Ids {
|
2020-07-25 23:21:15 +00:00
|
|
|
group_button,
|
2020-07-12 00:39:50 +00:00
|
|
|
bg,
|
|
|
|
title,
|
2020-08-05 11:29:42 +00:00
|
|
|
title_bg,
|
2020-07-12 00:39:50 +00:00
|
|
|
btn_bg,
|
|
|
|
btn_friend,
|
|
|
|
btn_leader,
|
|
|
|
btn_link,
|
|
|
|
btn_kick,
|
|
|
|
btn_leave,
|
2020-07-19 21:49:18 +00:00
|
|
|
scroll_area,
|
|
|
|
scrollbar,
|
2020-07-12 00:39:50 +00:00
|
|
|
members[],
|
|
|
|
bubble_frame,
|
|
|
|
btn_accept,
|
|
|
|
btn_decline,
|
2020-07-25 23:21:15 +00:00
|
|
|
member_panels_bg[],
|
|
|
|
member_panels_frame[],
|
|
|
|
member_panels_txt_bg[],
|
|
|
|
member_panels_txt[],
|
|
|
|
member_health[],
|
|
|
|
member_stam[],
|
|
|
|
dead_txt[],
|
|
|
|
health_txt[],
|
2020-08-04 07:22:59 +00:00
|
|
|
timeout_bg,
|
|
|
|
timeout,
|
2020-07-12 00:39:50 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub struct State {
|
|
|
|
ids: Ids,
|
|
|
|
// Selected group member
|
|
|
|
selected_member: Option<Uid>,
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(WidgetCommon)]
|
|
|
|
pub struct Group<'a> {
|
2020-07-19 21:49:18 +00:00
|
|
|
show: &'a mut Show,
|
2020-07-12 00:39:50 +00:00
|
|
|
client: &'a Client,
|
2020-07-19 21:49:18 +00:00
|
|
|
settings: &'a Settings,
|
2020-07-12 00:39:50 +00:00
|
|
|
imgs: &'a Imgs,
|
|
|
|
fonts: &'a ConrodVoxygenFonts,
|
|
|
|
localized_strings: &'a std::sync::Arc<VoxygenLocalization>,
|
2020-07-25 23:21:15 +00:00
|
|
|
pulse: f32,
|
|
|
|
global_state: &'a GlobalState,
|
2020-07-12 00:39:50 +00:00
|
|
|
|
|
|
|
#[conrod(common_builder)]
|
|
|
|
common: widget::CommonBuilder,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<'a> Group<'a> {
|
2020-08-04 07:22:59 +00:00
|
|
|
#[allow(clippy::too_many_arguments)] // TODO: Pending review in #587
|
2020-07-12 00:39:50 +00:00
|
|
|
pub fn new(
|
2020-07-19 21:49:18 +00:00
|
|
|
show: &'a mut Show,
|
2020-07-12 00:39:50 +00:00
|
|
|
client: &'a Client,
|
2020-07-19 21:49:18 +00:00
|
|
|
settings: &'a Settings,
|
2020-07-12 00:39:50 +00:00
|
|
|
imgs: &'a Imgs,
|
|
|
|
fonts: &'a ConrodVoxygenFonts,
|
|
|
|
localized_strings: &'a std::sync::Arc<VoxygenLocalization>,
|
2020-07-25 23:21:15 +00:00
|
|
|
pulse: f32,
|
|
|
|
global_state: &'a GlobalState,
|
2020-07-12 00:39:50 +00:00
|
|
|
) -> Self {
|
|
|
|
Self {
|
|
|
|
show,
|
|
|
|
client,
|
2020-07-19 21:49:18 +00:00
|
|
|
settings,
|
2020-07-12 00:39:50 +00:00
|
|
|
imgs,
|
|
|
|
fonts,
|
|
|
|
localized_strings,
|
2020-07-25 23:21:15 +00:00
|
|
|
pulse,
|
|
|
|
global_state,
|
2020-07-12 00:39:50 +00:00
|
|
|
common: widget::CommonBuilder::default(),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub enum Event {
|
|
|
|
Accept,
|
2020-07-19 21:49:18 +00:00
|
|
|
Decline,
|
2020-07-12 00:39:50 +00:00
|
|
|
Kick(Uid),
|
|
|
|
LeaveGroup,
|
|
|
|
AssignLeader(Uid),
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<'a> Widget for Group<'a> {
|
|
|
|
type Event = Vec<Event>;
|
|
|
|
type State = State;
|
|
|
|
type Style = ();
|
|
|
|
|
|
|
|
fn init_state(&self, id_gen: widget::id::Generator) -> Self::State {
|
|
|
|
Self::State {
|
|
|
|
ids: Ids::new(id_gen),
|
|
|
|
selected_member: None,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-08-04 07:22:59 +00:00
|
|
|
#[allow(clippy::blocks_in_if_conditions)] // TODO: Pending review in #587
|
2020-07-12 00:39:50 +00:00
|
|
|
fn style(&self) -> Self::Style { () }
|
|
|
|
|
2020-07-25 23:21:15 +00:00
|
|
|
//TODO: Disband groups when there's only one member in them
|
|
|
|
//TODO: Always send health, energy, level and position of group members to the
|
|
|
|
// client
|
2020-08-04 07:22:59 +00:00
|
|
|
#[allow(clippy::unused_unit)] // TODO: Pending review in #587
|
2020-07-12 00:39:50 +00:00
|
|
|
fn update(self, args: widget::UpdateArgs<Self>) -> Self::Event {
|
|
|
|
let widget::UpdateArgs { state, ui, .. } = args;
|
|
|
|
|
|
|
|
let mut events = Vec::new();
|
|
|
|
|
2020-07-19 21:49:18 +00:00
|
|
|
// Don't show pets
|
|
|
|
let group_members = self
|
|
|
|
.client
|
|
|
|
.group_members()
|
|
|
|
.iter()
|
|
|
|
.filter_map(|(u, r)| match r {
|
|
|
|
Role::Member => Some(u),
|
|
|
|
Role::Pet => None,
|
|
|
|
})
|
|
|
|
.collect::<Vec<_>>();
|
|
|
|
// Not considered in group for ui purposes if it is just pets
|
|
|
|
let in_group = !group_members.is_empty();
|
2020-07-31 03:46:08 +00:00
|
|
|
if !in_group {
|
|
|
|
self.show.group_menu = false;
|
2020-08-03 19:42:06 +00:00
|
|
|
self.show.group = false;
|
2020-07-31 03:46:08 +00:00
|
|
|
}
|
2020-07-19 21:49:18 +00:00
|
|
|
|
|
|
|
// Helper
|
|
|
|
let uid_to_name_text = |uid, client: &Client| match client.player_list.get(&uid) {
|
|
|
|
Some(player_info) => player_info
|
|
|
|
.character
|
|
|
|
.as_ref()
|
|
|
|
.map_or_else(|| format!("Player<{}>", uid), |c| c.name.clone()),
|
|
|
|
None => client
|
|
|
|
.state()
|
|
|
|
.ecs()
|
|
|
|
.entity_from_uid(uid.0)
|
|
|
|
.and_then(|entity| {
|
|
|
|
client
|
|
|
|
.state()
|
|
|
|
.ecs()
|
|
|
|
.read_storage::<Stats>()
|
|
|
|
.get(entity)
|
|
|
|
.map(|stats| stats.name.clone())
|
|
|
|
})
|
|
|
|
.unwrap_or_else(|| format!("Npc<{}>", uid)),
|
|
|
|
};
|
|
|
|
|
|
|
|
let open_invite = self.client.group_invite();
|
|
|
|
|
|
|
|
let my_uid = self.client.uid();
|
2020-07-12 00:39:50 +00:00
|
|
|
|
2020-07-19 21:49:18 +00:00
|
|
|
// TODO show something to the player when they click on the group button while
|
|
|
|
// they are not in a group so that it doesn't look like the button is
|
|
|
|
// broken
|
2020-07-25 23:21:15 +00:00
|
|
|
if self.show.group_menu || open_invite.is_some() {
|
2020-07-12 00:39:50 +00:00
|
|
|
// Frame
|
2020-08-05 11:29:42 +00:00
|
|
|
Rectangle::fill_with([220.0, 140.0], color::Color::Rgba(0.0, 0.0, 0.0, 0.8))
|
|
|
|
.bottom_left_with_margins_on(ui.window, 108.0, 490.0)
|
2020-08-03 19:42:06 +00:00
|
|
|
.crop_kids()
|
2020-07-12 00:39:50 +00:00
|
|
|
.set(state.ids.bg, ui);
|
|
|
|
}
|
2020-07-25 23:21:15 +00:00
|
|
|
if open_invite.is_some() {
|
|
|
|
// Group Menu button
|
|
|
|
Button::image(self.imgs.group_icon)
|
|
|
|
.w_h(49.0, 26.0)
|
2020-08-05 11:29:42 +00:00
|
|
|
.bottom_left_with_margins_on(ui.window, 10.0, 490.0)
|
2020-07-25 23:21:15 +00:00
|
|
|
.set(state.ids.group_button, ui);
|
2020-08-04 07:22:59 +00:00
|
|
|
// Show timeout bar
|
|
|
|
let max_time = 90.0;
|
|
|
|
let time = 50.0;
|
|
|
|
let progress_perc = time / max_time;
|
|
|
|
Image::new(self.imgs.progress_frame)
|
|
|
|
.w_h(100.0, 10.0)
|
|
|
|
.middle_of(state.ids.bg)
|
|
|
|
.color(Some(UI_MAIN))
|
|
|
|
.set(state.ids.timeout_bg, ui);
|
|
|
|
Image::new(self.imgs.progress)
|
|
|
|
.w_h(98.0 * progress_perc, 8.0)
|
|
|
|
.top_left_with_margins_on(state.ids.timeout_bg, 1.0, 1.0)
|
|
|
|
.color(Some(UI_HIGHLIGHT_0))
|
|
|
|
.set(state.ids.timeout, ui);
|
2020-07-25 23:21:15 +00:00
|
|
|
}
|
2020-07-12 00:39:50 +00:00
|
|
|
// Buttons
|
2020-07-19 21:49:18 +00:00
|
|
|
if let Some((group_name, leader)) = self.client.group_info().filter(|_| in_group) {
|
2020-07-25 23:21:15 +00:00
|
|
|
// Group Menu Button
|
|
|
|
if Button::image(if self.show.group_menu {
|
|
|
|
self.imgs.group_icon_press
|
|
|
|
} else {
|
|
|
|
self.imgs.group_icon
|
|
|
|
})
|
|
|
|
.w_h(49.0, 26.0)
|
2020-08-05 11:29:42 +00:00
|
|
|
.bottom_left_with_margins_on(ui.window, 10.0, 490.0)
|
2020-07-25 23:21:15 +00:00
|
|
|
.hover_image(self.imgs.group_icon_hover)
|
|
|
|
.press_image(self.imgs.group_icon_press)
|
|
|
|
.set(state.ids.group_button, ui)
|
|
|
|
.was_clicked()
|
|
|
|
{
|
|
|
|
self.show.group_menu = !self.show.group_menu;
|
|
|
|
};
|
2020-08-05 11:29:42 +00:00
|
|
|
Text::new(&group_name)
|
|
|
|
.up_from(state.ids.group_button, 5.0)
|
|
|
|
.font_size(14)
|
|
|
|
.font_id(self.fonts.cyri.conrod_id)
|
|
|
|
.color(BLACK)
|
|
|
|
.set(state.ids.title_bg, ui);
|
|
|
|
Text::new(&group_name)
|
|
|
|
.bottom_right_with_margins_on(state.ids.title_bg, 1.0, 1.0)
|
|
|
|
.font_size(14)
|
|
|
|
.font_id(self.fonts.cyri.conrod_id)
|
|
|
|
.color(TEXT_COLOR)
|
|
|
|
.set(state.ids.title, ui);
|
2020-07-25 23:21:15 +00:00
|
|
|
// Member panels
|
2020-07-31 03:46:08 +00:00
|
|
|
let group_size = group_members.len();
|
2020-07-25 23:21:15 +00:00
|
|
|
if state.ids.member_panels_bg.len() < group_size {
|
|
|
|
state.update(|s| {
|
|
|
|
s.ids
|
|
|
|
.member_panels_bg
|
|
|
|
.resize(group_size, &mut ui.widget_id_generator())
|
|
|
|
})
|
|
|
|
};
|
|
|
|
if state.ids.member_health.len() < group_size {
|
|
|
|
state.update(|s| {
|
|
|
|
s.ids
|
|
|
|
.member_health
|
|
|
|
.resize(group_size, &mut ui.widget_id_generator())
|
|
|
|
})
|
|
|
|
};
|
|
|
|
if state.ids.member_stam.len() < group_size {
|
|
|
|
state.update(|s| {
|
|
|
|
s.ids
|
|
|
|
.member_stam
|
|
|
|
.resize(group_size, &mut ui.widget_id_generator())
|
|
|
|
})
|
|
|
|
};
|
|
|
|
if state.ids.member_panels_frame.len() < group_size {
|
|
|
|
state.update(|s| {
|
|
|
|
s.ids
|
|
|
|
.member_panels_frame
|
|
|
|
.resize(group_size, &mut ui.widget_id_generator())
|
|
|
|
})
|
|
|
|
};
|
|
|
|
if state.ids.member_panels_txt.len() < group_size {
|
|
|
|
state.update(|s| {
|
|
|
|
s.ids
|
|
|
|
.member_panels_txt
|
|
|
|
.resize(group_size, &mut ui.widget_id_generator())
|
|
|
|
})
|
|
|
|
};
|
|
|
|
if state.ids.dead_txt.len() < group_size {
|
|
|
|
state.update(|s| {
|
|
|
|
s.ids
|
|
|
|
.dead_txt
|
|
|
|
.resize(group_size, &mut ui.widget_id_generator())
|
|
|
|
})
|
|
|
|
};
|
|
|
|
if state.ids.health_txt.len() < group_size {
|
|
|
|
state.update(|s| {
|
|
|
|
s.ids
|
|
|
|
.health_txt
|
|
|
|
.resize(group_size, &mut ui.widget_id_generator())
|
|
|
|
})
|
|
|
|
};
|
|
|
|
if state.ids.member_panels_txt_bg.len() < group_size {
|
|
|
|
state.update(|s| {
|
|
|
|
s.ids
|
|
|
|
.member_panels_txt_bg
|
|
|
|
.resize(group_size, &mut ui.widget_id_generator())
|
|
|
|
})
|
|
|
|
};
|
|
|
|
|
|
|
|
let client_state = self.client.state();
|
|
|
|
let stats = client_state.ecs().read_storage::<common::comp::Stats>();
|
|
|
|
let energy = client_state.ecs().read_storage::<common::comp::Energy>();
|
|
|
|
let uid_allocator = client_state
|
|
|
|
.ecs()
|
|
|
|
.read_resource::<common::sync::UidAllocator>();
|
|
|
|
|
2020-07-31 03:46:08 +00:00
|
|
|
for (i, &uid) in group_members.iter().copied().enumerate() {
|
2020-07-25 23:21:15 +00:00
|
|
|
self.show.group = true;
|
|
|
|
let entity = uid_allocator.retrieve_entity_internal(uid.into());
|
|
|
|
let stats = entity.and_then(|entity| stats.get(entity));
|
|
|
|
let energy = entity.and_then(|entity| energy.get(entity));
|
|
|
|
if let Some(stats) = stats {
|
|
|
|
let char_name = stats.name.to_string();
|
|
|
|
let health_perc = stats.health.current() as f64 / stats.health.maximum() as f64;
|
|
|
|
|
|
|
|
// change panel positions when debug info is shown
|
|
|
|
let offset = if self.global_state.settings.gameplay.toggle_debug {
|
2020-08-05 11:29:42 +00:00
|
|
|
290.0
|
2020-07-25 23:21:15 +00:00
|
|
|
} else {
|
|
|
|
110.0
|
|
|
|
};
|
2020-07-31 03:46:08 +00:00
|
|
|
let back = if i == 0 {
|
2020-07-25 23:21:15 +00:00
|
|
|
Image::new(self.imgs.member_bg)
|
|
|
|
.top_left_with_margins_on(ui.window, offset, 20.0)
|
|
|
|
} else {
|
|
|
|
Image::new(self.imgs.member_bg)
|
|
|
|
.down_from(state.ids.member_panels_bg[i - 1], 40.0)
|
|
|
|
};
|
|
|
|
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 health_col = match (health_perc * 100.0) as u8 {
|
|
|
|
0..=20 => crit_hp_color,
|
|
|
|
21..=40 => LOW_HP_COLOR,
|
|
|
|
_ => HP_COLOR,
|
|
|
|
};
|
2020-08-05 11:29:42 +00:00
|
|
|
let lead = if uid == leader { true } else { false };
|
2020-07-25 23:21:15 +00:00
|
|
|
// Don't show panel for the player!
|
|
|
|
// Panel BG
|
2020-07-31 03:46:08 +00:00
|
|
|
back.w_h(152.0, 36.0)
|
2020-08-05 11:29:42 +00:00
|
|
|
.color(if lead {
|
|
|
|
Some(ERROR_COLOR)
|
|
|
|
} else {
|
|
|
|
Some(TEXT_COLOR)
|
|
|
|
})
|
2020-07-25 23:21:15 +00:00
|
|
|
.set(state.ids.member_panels_bg[i], ui);
|
|
|
|
// Health
|
|
|
|
Image::new(self.imgs.bar_content)
|
|
|
|
.w_h(148.0 * health_perc, 22.0)
|
2020-07-31 03:46:08 +00:00
|
|
|
.color(Some(health_col))
|
2020-07-25 23:21:15 +00:00
|
|
|
.top_left_with_margins_on(state.ids.member_panels_bg[i], 2.0, 2.0)
|
|
|
|
.set(state.ids.member_health[i], ui);
|
|
|
|
if stats.is_dead {
|
|
|
|
// Death Text
|
|
|
|
Text::new(&self.localized_strings.get("hud.group.dead"))
|
|
|
|
.mid_top_with_margin_on(state.ids.member_panels_bg[i], 1.0)
|
|
|
|
.font_size(20)
|
|
|
|
.font_id(self.fonts.cyri.conrod_id)
|
2020-07-31 03:46:08 +00:00
|
|
|
.color(KILL_COLOR)
|
2020-07-25 23:21:15 +00:00
|
|
|
.set(state.ids.dead_txt[i], ui);
|
|
|
|
} else {
|
|
|
|
// Health Text
|
|
|
|
let txt = format!(
|
|
|
|
"{}/{}",
|
2020-08-02 23:53:02 +00:00
|
|
|
stats.health.current() / 10 as u32,
|
|
|
|
stats.health.maximum() / 10 as u32,
|
2020-07-25 23:21:15 +00:00
|
|
|
);
|
2020-08-02 23:53:02 +00:00
|
|
|
// Change font size depending on health amount
|
2020-07-25 23:21:15 +00:00
|
|
|
let font_size = match stats.health.maximum() {
|
|
|
|
0..=999 => 14,
|
|
|
|
1000..=9999 => 13,
|
|
|
|
10000..=99999 => 12,
|
|
|
|
_ => 11,
|
|
|
|
};
|
2020-08-02 23:53:02 +00:00
|
|
|
// Change text offset depending on health amount
|
2020-07-25 23:21:15 +00:00
|
|
|
let txt_offset = match stats.health.maximum() {
|
|
|
|
0..=999 => 4.0,
|
|
|
|
1000..=9999 => 4.5,
|
|
|
|
10000..=99999 => 5.0,
|
|
|
|
_ => 5.5,
|
|
|
|
};
|
|
|
|
Text::new(&txt)
|
|
|
|
.mid_top_with_margin_on(state.ids.member_panels_bg[i], txt_offset)
|
|
|
|
.font_size(font_size)
|
|
|
|
.font_id(self.fonts.cyri.conrod_id)
|
2020-07-31 03:46:08 +00:00
|
|
|
.color(Color::Rgba(1.0, 1.0, 1.0, 0.5))
|
2020-07-25 23:21:15 +00:00
|
|
|
.set(state.ids.health_txt[i], ui);
|
|
|
|
};
|
|
|
|
// Panel Frame
|
|
|
|
Image::new(self.imgs.member_frame)
|
|
|
|
.w_h(152.0, 36.0)
|
|
|
|
.middle_of(state.ids.member_panels_bg[i])
|
2020-07-31 03:46:08 +00:00
|
|
|
.color(Some(UI_HIGHLIGHT_0))
|
2020-07-25 23:21:15 +00:00
|
|
|
.set(state.ids.member_panels_frame[i], ui);
|
|
|
|
// Panel Text
|
|
|
|
Text::new(&char_name)
|
|
|
|
.top_left_with_margins_on(state.ids.member_panels_frame[i], -22.0, 0.0)
|
|
|
|
.font_size(20)
|
|
|
|
.font_id(self.fonts.cyri.conrod_id)
|
2020-07-31 03:46:08 +00:00
|
|
|
.color(BLACK)
|
2020-08-05 11:29:42 +00:00
|
|
|
.w(300.0) // limit name length display
|
2020-07-25 23:21:15 +00:00
|
|
|
.set(state.ids.member_panels_txt_bg[i], ui);
|
|
|
|
Text::new(&char_name)
|
|
|
|
.bottom_left_with_margins_on(state.ids.member_panels_txt_bg[i], 2.0, 2.0)
|
|
|
|
.font_size(20)
|
|
|
|
.font_id(self.fonts.cyri.conrod_id)
|
2020-08-05 11:29:42 +00:00
|
|
|
.color(if lead { ERROR_COLOR } else { GROUP_COLOR })
|
|
|
|
.w(300.0) // limit name length display
|
2020-07-25 23:21:15 +00:00
|
|
|
.set(state.ids.member_panels_txt[i], ui);
|
|
|
|
if let Some(energy) = energy {
|
|
|
|
let stam_perc = energy.current() as f64 / energy.maximum() as f64;
|
|
|
|
// Stamina
|
|
|
|
Image::new(self.imgs.bar_content)
|
|
|
|
.w_h(100.0 * stam_perc, 8.0)
|
2020-07-31 03:46:08 +00:00
|
|
|
.color(Some(MANA_COLOR))
|
2020-07-25 23:21:15 +00:00
|
|
|
.top_left_with_margins_on(state.ids.member_panels_bg[i], 26.0, 2.0)
|
|
|
|
.set(state.ids.member_stam[i], ui);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
// Values N.A.
|
|
|
|
if let Some(stats) = stats {
|
|
|
|
Text::new(&stats.name.to_string())
|
|
|
|
.top_left_with_margins_on(state.ids.member_panels_frame[i], -22.0, 0.0)
|
|
|
|
.font_size(20)
|
|
|
|
.font_id(self.fonts.cyri.conrod_id)
|
|
|
|
.color(GROUP_COLOR)
|
|
|
|
.set(state.ids.member_panels_txt[i], ui);
|
|
|
|
};
|
|
|
|
let offset = if self.global_state.settings.gameplay.toggle_debug {
|
|
|
|
210.0
|
|
|
|
} else {
|
|
|
|
110.0
|
|
|
|
};
|
2020-07-31 03:46:08 +00:00
|
|
|
let back = if i == 0 {
|
2020-07-25 23:21:15 +00:00
|
|
|
Image::new(self.imgs.member_bg)
|
|
|
|
.top_left_with_margins_on(ui.window, offset, 20.0)
|
|
|
|
} else {
|
|
|
|
Image::new(self.imgs.member_bg)
|
|
|
|
.down_from(state.ids.member_panels_bg[i - 1], 40.0)
|
|
|
|
};
|
2020-07-31 03:46:08 +00:00
|
|
|
back.w_h(152.0, 36.0)
|
|
|
|
.color(Some(TEXT_COLOR))
|
2020-07-25 23:21:15 +00:00
|
|
|
.set(state.ids.member_panels_bg[i], ui);
|
|
|
|
// Panel Frame
|
|
|
|
Image::new(self.imgs.member_frame)
|
|
|
|
.w_h(152.0, 36.0)
|
|
|
|
.middle_of(state.ids.member_panels_bg[i])
|
2020-07-31 03:46:08 +00:00
|
|
|
.color(Some(UI_HIGHLIGHT_0))
|
2020-07-25 23:21:15 +00:00
|
|
|
.set(state.ids.member_panels_frame[i], ui);
|
|
|
|
// Panel Text
|
|
|
|
Text::new(&self.localized_strings.get("hud.group.out_of_range"))
|
|
|
|
.mid_top_with_margin_on(state.ids.member_panels_bg[i], 3.0)
|
|
|
|
.font_size(16)
|
|
|
|
.font_id(self.fonts.cyri.conrod_id)
|
2020-07-31 03:46:08 +00:00
|
|
|
.color(TEXT_COLOR)
|
2020-07-25 23:21:15 +00:00
|
|
|
.set(state.ids.dead_txt[i], ui);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if self.show.group_menu {
|
|
|
|
let selected = state.selected_member;
|
2020-08-05 11:29:42 +00:00
|
|
|
if Button::image(self.imgs.button) // Change button behaviour and style when the friendslist is working
|
2020-08-02 23:53:02 +00:00
|
|
|
.w_h(90.0, 22.0)
|
2020-08-05 11:29:42 +00:00
|
|
|
.top_right_with_margins_on(state.ids.bg, 5.0, 5.0)
|
|
|
|
.hover_image(self.imgs.button)
|
|
|
|
.press_image(self.imgs.button)
|
|
|
|
.label_color(TEXT_COLOR_GREY)
|
|
|
|
.image_color(TEXT_COLOR_GREY)
|
2020-08-02 23:53:02 +00:00
|
|
|
.label(&self.localized_strings.get("hud.group.add_friend"))
|
|
|
|
.label_font_id(self.fonts.cyri.conrod_id)
|
|
|
|
.label_font_size(self.fonts.cyri.scale(10))
|
|
|
|
.set(state.ids.btn_friend, ui)
|
|
|
|
.was_clicked()
|
2020-07-25 23:21:15 +00:00
|
|
|
{};
|
2020-07-19 21:49:18 +00:00
|
|
|
if Button::image(self.imgs.button)
|
|
|
|
.w_h(90.0, 22.0)
|
2020-07-25 23:21:15 +00:00
|
|
|
.bottom_right_with_margins_on(state.ids.bg, 5.0, 5.0)
|
2020-07-19 21:49:18 +00:00
|
|
|
.hover_image(self.imgs.button_hover)
|
|
|
|
.press_image(self.imgs.button_press)
|
2020-07-25 23:21:15 +00:00
|
|
|
.label(&self.localized_strings.get("hud.group.leave"))
|
|
|
|
.label_color(TEXT_COLOR)
|
2020-07-19 21:49:18 +00:00
|
|
|
.label_font_id(self.fonts.cyri.conrod_id)
|
|
|
|
.label_font_size(self.fonts.cyri.scale(10))
|
2020-07-25 23:21:15 +00:00
|
|
|
.set(state.ids.btn_leave, ui)
|
2020-07-19 21:49:18 +00:00
|
|
|
.was_clicked()
|
|
|
|
{
|
2020-07-25 23:21:15 +00:00
|
|
|
self.show.group_menu = false;
|
2020-08-02 23:53:02 +00:00
|
|
|
self.show.group = !self.show.group;
|
2020-07-25 23:21:15 +00:00
|
|
|
events.push(Event::LeaveGroup);
|
2020-07-19 21:49:18 +00:00
|
|
|
};
|
2020-07-25 23:21:15 +00:00
|
|
|
// Group leader functions
|
|
|
|
if my_uid == Some(leader) {
|
|
|
|
if Button::image(self.imgs.button)
|
|
|
|
.w_h(90.0, 22.0)
|
|
|
|
.mid_bottom_with_margin_on(state.ids.btn_friend, -27.0)
|
|
|
|
.hover_image(self.imgs.button_hover)
|
|
|
|
.press_image(self.imgs.button_press)
|
|
|
|
.label(&self.localized_strings.get("hud.group.assign_leader"))
|
|
|
|
.label_color(if state.selected_member.is_some() {
|
|
|
|
TEXT_COLOR
|
|
|
|
} else {
|
|
|
|
TEXT_COLOR_GREY
|
|
|
|
})
|
|
|
|
.label_font_id(self.fonts.cyri.conrod_id)
|
|
|
|
.label_font_size(self.fonts.cyri.scale(10))
|
|
|
|
.set(state.ids.btn_leader, ui)
|
|
|
|
.was_clicked()
|
|
|
|
{
|
|
|
|
if let Some(uid) = selected {
|
|
|
|
events.push(Event::AssignLeader(uid));
|
|
|
|
state.update(|s| {
|
|
|
|
s.selected_member = None;
|
|
|
|
});
|
|
|
|
}
|
|
|
|
};
|
|
|
|
if Button::image(self.imgs.button)
|
2020-08-05 11:29:42 +00:00
|
|
|
.w_h(90.0, 22.0)
|
|
|
|
.mid_bottom_with_margin_on(state.ids.btn_leader, -27.0)
|
|
|
|
.hover_image(self.imgs.button)
|
|
|
|
.press_image(self.imgs.button)
|
|
|
|
.label(&self.localized_strings.get("hud.group.link_group"))
|
|
|
|
.hover_image(self.imgs.button)
|
|
|
|
.press_image(self.imgs.button)
|
|
|
|
.label_color(TEXT_COLOR_GREY)
|
|
|
|
.image_color(TEXT_COLOR_GREY)
|
|
|
|
.label_font_id(self.fonts.cyri.conrod_id)
|
|
|
|
.label_font_size(self.fonts.cyri.scale(10))
|
|
|
|
.set(state.ids.btn_link, ui)
|
|
|
|
.was_clicked()
|
2020-07-25 23:21:15 +00:00
|
|
|
{};
|
|
|
|
if Button::image(self.imgs.button)
|
|
|
|
.w_h(90.0, 22.0)
|
|
|
|
.mid_bottom_with_margin_on(state.ids.btn_link, -27.0)
|
|
|
|
.down_from(state.ids.btn_link, 5.0)
|
|
|
|
.hover_image(self.imgs.button_hover)
|
|
|
|
.press_image(self.imgs.button_press)
|
|
|
|
.label(&self.localized_strings.get("hud.group.kick"))
|
|
|
|
.label_color(if state.selected_member.is_some() {
|
|
|
|
TEXT_COLOR
|
|
|
|
} else {
|
|
|
|
TEXT_COLOR_GREY
|
|
|
|
})
|
|
|
|
.label_font_id(self.fonts.cyri.conrod_id)
|
|
|
|
.label_font_size(self.fonts.cyri.scale(10))
|
|
|
|
.set(state.ids.btn_kick, ui)
|
|
|
|
.was_clicked()
|
|
|
|
{
|
|
|
|
if let Some(uid) = selected {
|
|
|
|
events.push(Event::Kick(uid));
|
|
|
|
state.update(|s| {
|
|
|
|
s.selected_member = None;
|
|
|
|
});
|
|
|
|
}
|
|
|
|
};
|
|
|
|
}
|
|
|
|
// Group Members, only character names, cut long names when they exceed the
|
|
|
|
// button size
|
2020-07-31 03:46:08 +00:00
|
|
|
let group_size = group_members.len();
|
2020-07-25 23:21:15 +00:00
|
|
|
if state.ids.members.len() < group_size {
|
|
|
|
state.update(|s| {
|
|
|
|
s.ids
|
|
|
|
.members
|
|
|
|
.resize(group_size, &mut ui.widget_id_generator())
|
2020-07-19 21:49:18 +00:00
|
|
|
})
|
2020-07-25 23:21:15 +00:00
|
|
|
}
|
|
|
|
// Scrollable area for group member names
|
2020-08-02 23:53:02 +00:00
|
|
|
Rectangle::fill_with([110.0, 135.0], color::TRANSPARENT)
|
2020-08-05 11:29:42 +00:00
|
|
|
.top_left_with_margins_on(state.ids.bg, 5.0, 5.0)
|
|
|
|
.crop_kids()
|
2020-07-25 23:21:15 +00:00
|
|
|
.scroll_kids_vertically()
|
|
|
|
.set(state.ids.scroll_area, ui);
|
|
|
|
Scrollbar::y_axis(state.ids.scroll_area)
|
|
|
|
.thickness(5.0)
|
|
|
|
.rgba(0.33, 0.33, 0.33, 1.0)
|
|
|
|
.set(state.ids.scrollbar, ui);
|
|
|
|
// List member names
|
2020-07-31 03:46:08 +00:00
|
|
|
for (i, &uid) in group_members.iter().copied().enumerate() {
|
2020-07-25 23:21:15 +00:00
|
|
|
let selected = state.selected_member.map_or(false, |u| u == uid);
|
|
|
|
let char_name = uid_to_name_text(uid, &self.client);
|
|
|
|
// TODO: Do something special visually if uid == leader
|
|
|
|
if Button::image(if selected {
|
|
|
|
self.imgs.selection
|
2020-07-19 21:49:18 +00:00
|
|
|
} else {
|
2020-07-25 23:21:15 +00:00
|
|
|
self.imgs.nothing
|
|
|
|
})
|
|
|
|
.w_h(100.0, 22.0)
|
|
|
|
.and(|w| {
|
|
|
|
if i == 0 {
|
|
|
|
w.top_left_with_margins_on(state.ids.scroll_area, 5.0, 0.0)
|
|
|
|
} else {
|
2020-08-02 23:53:02 +00:00
|
|
|
w.down_from(state.ids.members[i - 1], 5.0)
|
2020-07-25 23:21:15 +00:00
|
|
|
}
|
|
|
|
})
|
|
|
|
.hover_image(self.imgs.selection_hover)
|
|
|
|
.press_image(self.imgs.selection_press)
|
|
|
|
.crop_kids()
|
|
|
|
.label_x(Relative::Place(Place::Start(Some(4.0))))
|
|
|
|
.label(&char_name)
|
2020-08-05 11:29:42 +00:00
|
|
|
.label_color(if uid == leader {
|
|
|
|
ERROR_COLOR
|
|
|
|
} else {
|
|
|
|
TEXT_COLOR
|
|
|
|
})
|
2020-07-25 23:21:15 +00:00
|
|
|
.label_font_id(self.fonts.cyri.conrod_id)
|
|
|
|
.label_font_size(self.fonts.cyri.scale(12))
|
|
|
|
.set(state.ids.members[i], ui)
|
|
|
|
.was_clicked()
|
|
|
|
{
|
|
|
|
// Do nothing when clicking yourself
|
|
|
|
if Some(uid) != my_uid {
|
|
|
|
// Select the group member
|
|
|
|
state.update(|s| {
|
|
|
|
s.selected_member = if selected { None } else { Some(uid) }
|
|
|
|
});
|
|
|
|
}
|
|
|
|
};
|
|
|
|
}
|
|
|
|
// Maximum of 6 Players/Npcs per Group
|
|
|
|
// Player pets count as group members, too. They are not counted
|
|
|
|
// into the maximum group size.
|
2020-07-19 21:49:18 +00:00
|
|
|
}
|
2020-07-12 00:39:50 +00:00
|
|
|
}
|
2020-07-19 21:49:18 +00:00
|
|
|
if let Some(invite_uid) = open_invite {
|
|
|
|
self.show.group = true; // Auto open group menu
|
|
|
|
// TODO: add group name here too
|
|
|
|
// Invite text
|
2020-07-25 23:21:15 +00:00
|
|
|
|
2020-07-19 21:49:18 +00:00
|
|
|
let name = uid_to_name_text(invite_uid, &self.client);
|
|
|
|
let invite_text = self
|
|
|
|
.localized_strings
|
|
|
|
.get("hud.group.invite_to_join")
|
|
|
|
.replace("{name}", &name);
|
|
|
|
Text::new(&invite_text)
|
2020-08-05 11:29:42 +00:00
|
|
|
.mid_top_with_margin_on(state.ids.bg, 5.0)
|
2020-07-25 23:21:15 +00:00
|
|
|
.font_size(12)
|
2020-07-12 00:39:50 +00:00
|
|
|
.font_id(self.fonts.cyri.conrod_id)
|
|
|
|
.color(TEXT_COLOR)
|
2020-08-05 11:29:42 +00:00
|
|
|
.w(165.0) // Text stays within frame
|
2020-07-12 00:39:50 +00:00
|
|
|
.set(state.ids.title, ui);
|
2020-07-19 21:49:18 +00:00
|
|
|
// Accept Button
|
|
|
|
let accept_key = self
|
|
|
|
.settings
|
|
|
|
.controls
|
|
|
|
.get_binding(GameInput::AcceptGroupInvite)
|
|
|
|
.map_or_else(|| "".into(), |key| key.to_string());
|
2020-07-12 00:39:50 +00:00
|
|
|
if Button::image(self.imgs.button)
|
|
|
|
.w_h(90.0, 22.0)
|
|
|
|
.bottom_left_with_margins_on(state.ids.bg, 15.0, 15.0)
|
2020-07-19 21:49:18 +00:00
|
|
|
.hover_image(self.imgs.button_hover)
|
|
|
|
.press_image(self.imgs.button_press)
|
|
|
|
.label(&format!(
|
|
|
|
"[{}] {}",
|
|
|
|
&accept_key,
|
|
|
|
&self.localized_strings.get("common.accept")
|
|
|
|
))
|
|
|
|
.label_color(TEXT_COLOR)
|
2020-07-12 00:39:50 +00:00
|
|
|
.label_font_id(self.fonts.cyri.conrod_id)
|
2020-08-05 11:29:42 +00:00
|
|
|
.label_font_size(self.fonts.cyri.scale(12))
|
2020-07-19 21:49:18 +00:00
|
|
|
.set(state.ids.btn_accept, ui)
|
2020-07-12 00:39:50 +00:00
|
|
|
.was_clicked()
|
2020-07-19 21:49:18 +00:00
|
|
|
{
|
|
|
|
events.push(Event::Accept);
|
2020-07-25 23:21:15 +00:00
|
|
|
self.show.group_menu = true;
|
2020-07-19 21:49:18 +00:00
|
|
|
};
|
|
|
|
// Decline button
|
|
|
|
let decline_key = self
|
|
|
|
.settings
|
|
|
|
.controls
|
|
|
|
.get_binding(GameInput::DeclineGroupInvite)
|
|
|
|
.map_or_else(|| "".into(), |key| key.to_string());
|
2020-07-12 00:39:50 +00:00
|
|
|
if Button::image(self.imgs.button)
|
|
|
|
.w_h(90.0, 22.0)
|
|
|
|
.bottom_right_with_margins_on(state.ids.bg, 15.0, 15.0)
|
2020-07-19 21:49:18 +00:00
|
|
|
.hover_image(self.imgs.button_hover)
|
|
|
|
.press_image(self.imgs.button_press)
|
|
|
|
.label(&format!(
|
|
|
|
"[{}] {}",
|
|
|
|
&decline_key,
|
|
|
|
&self.localized_strings.get("common.decline")
|
|
|
|
))
|
|
|
|
.label_color(TEXT_COLOR)
|
2020-07-12 00:39:50 +00:00
|
|
|
.label_font_id(self.fonts.cyri.conrod_id)
|
2020-08-05 11:29:42 +00:00
|
|
|
.label_font_size(self.fonts.cyri.scale(12))
|
2020-07-19 21:49:18 +00:00
|
|
|
.set(state.ids.btn_decline, ui)
|
2020-07-12 00:39:50 +00:00
|
|
|
.was_clicked()
|
2020-07-19 21:49:18 +00:00
|
|
|
{
|
|
|
|
events.push(Event::Decline);
|
|
|
|
};
|
2020-07-12 00:39:50 +00:00
|
|
|
}
|
2020-07-25 23:21:15 +00:00
|
|
|
|
2020-07-12 00:39:50 +00:00
|
|
|
events
|
|
|
|
}
|
|
|
|
}
|