mirror of
https://gitlab.com/veloren/veloren.git
synced 2024-08-30 18:12:32 +00:00
Added overhead hints, smoother mount movement
This commit is contained in:
parent
f33c12e976
commit
504e2a38d5
@ -26,7 +26,7 @@
|
||||
"hud.tutorial_elements": r#"Crafting"#,
|
||||
|
||||
"hud.temp_quest_headline": r#"Greetings Traveller!"#,
|
||||
"hud.temp_quest_text": r#"To begin your journey you could start looking through this village and gather some supplies.
|
||||
"hud.temp_quest_text": r#"To begin your journey you could start looking through this village and gather some supplies.
|
||||
|
||||
You are welcome to take whatever you need on your journey!
|
||||
|
||||
@ -46,6 +46,13 @@ Whenever you feel ready, try to get even better equipment from the many challeng
|
||||
"hud.free_look_indicator": "Free look active. Press {key} to disable.",
|
||||
"hud.camera_clamp_indicator": "Camera vertical clamp active. Press {key} to disable.",
|
||||
"hud.auto_walk_indicator": "Auto walk/swim active",
|
||||
"hud.collect": "Collect",
|
||||
"hud.pick_up": "Pick up",
|
||||
"hud.open": "Open",
|
||||
"hud.use": "Use",
|
||||
"hud.talk": "Talk",
|
||||
"hud.trade": "Trade",
|
||||
"hud.mount": "Mount",
|
||||
},
|
||||
|
||||
|
||||
|
@ -44,6 +44,7 @@ sum_type! {
|
||||
Ori(comp::Ori),
|
||||
Shockwave(comp::Shockwave),
|
||||
BeamSegment(comp::BeamSegment),
|
||||
Alignment(comp::Alignment),
|
||||
}
|
||||
}
|
||||
// Automatically derive From<T> for EcsCompPhantom
|
||||
@ -80,6 +81,7 @@ sum_type! {
|
||||
Ori(PhantomData<comp::Ori>),
|
||||
Shockwave(PhantomData<comp::Shockwave>),
|
||||
BeamSegment(PhantomData<comp::BeamSegment>),
|
||||
Alignment(PhantomData<comp::Alignment>),
|
||||
}
|
||||
}
|
||||
impl sync::CompPacket for EcsCompPacket {
|
||||
@ -127,6 +129,7 @@ impl sync::CompPacket for EcsCompPacket {
|
||||
},
|
||||
EcsCompPacket::Shockwave(comp) => sync::handle_insert(comp, entity, world),
|
||||
EcsCompPacket::BeamSegment(comp) => sync::handle_insert(comp, entity, world),
|
||||
EcsCompPacket::Alignment(comp) => sync::handle_insert(comp, entity, world),
|
||||
}
|
||||
}
|
||||
|
||||
@ -172,6 +175,7 @@ impl sync::CompPacket for EcsCompPacket {
|
||||
},
|
||||
EcsCompPacket::Shockwave(comp) => sync::handle_modify(comp, entity, world),
|
||||
EcsCompPacket::BeamSegment(comp) => sync::handle_modify(comp, entity, world),
|
||||
EcsCompPacket::Alignment(comp) => sync::handle_modify(comp, entity, world),
|
||||
}
|
||||
}
|
||||
|
||||
@ -211,7 +215,8 @@ impl sync::CompPacket for EcsCompPacket {
|
||||
EcsCompPhantom::Vel(_) => sync::handle_interp_remove::<comp::Vel>(entity, world),
|
||||
EcsCompPhantom::Ori(_) => sync::handle_interp_remove::<comp::Ori>(entity, world),
|
||||
EcsCompPhantom::Shockwave(_) => sync::handle_remove::<comp::Shockwave>(entity, world),
|
||||
EcsCompPhantom::BeamSegment(_) => sync::handle_remove::<comp::Ori>(entity, world),
|
||||
EcsCompPhantom::BeamSegment(_) => sync::handle_remove::<comp::BeamSegment>(entity, world),
|
||||
EcsCompPhantom::Alignment(_) => sync::handle_remove::<comp::Alignment>(entity, world),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -8,8 +8,8 @@ use crate::{
|
||||
trade::{PendingTrade, ReducedInventory, SiteId, SitePrices, TradeId, TradeResult},
|
||||
uid::Uid,
|
||||
};
|
||||
use serde::Deserialize;
|
||||
use specs::{Component, Entity as EcsEntity};
|
||||
use serde::{Serialize, Deserialize};
|
||||
use specs::{Component, Entity as EcsEntity, DerefFlaggedStorage};
|
||||
use specs_idvs::IdvStorage;
|
||||
use std::{collections::VecDeque, fmt};
|
||||
use strum::IntoEnumIterator;
|
||||
@ -21,7 +21,7 @@ use super::dialogue::Subject;
|
||||
pub const DEFAULT_INTERACTION_TIME: f32 = 3.0;
|
||||
pub const TRADE_INTERACTION_TIME: f32 = 300.0;
|
||||
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Deserialize)]
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Serialize, Deserialize)]
|
||||
pub enum Alignment {
|
||||
/// Wild animals and gentle giants
|
||||
Wild,
|
||||
@ -79,7 +79,7 @@ impl Alignment {
|
||||
}
|
||||
|
||||
impl Component for Alignment {
|
||||
type Storage = IdvStorage<Self>;
|
||||
type Storage = DerefFlaggedStorage<Self, IdvStorage<Self>>;
|
||||
}
|
||||
|
||||
bitflags::bitflags! {
|
||||
|
@ -10,7 +10,7 @@ use crate::{
|
||||
util::Dir,
|
||||
};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use specs::{Component, DerefFlaggedStorage};
|
||||
use specs::Component;
|
||||
use specs_idvs::IdvStorage;
|
||||
use std::collections::BTreeMap;
|
||||
use vek::*;
|
||||
|
@ -1,6 +1,6 @@
|
||||
// The limit on distance between the entity and a collectible (squared)
|
||||
pub const MAX_PICKUP_RANGE: f32 = 5.0;
|
||||
pub const MAX_MOUNT_RANGE: f32 = 14.0;
|
||||
pub const MAX_MOUNT_RANGE: f32 = 5.0;
|
||||
pub const MAX_TRADE_RANGE: f32 = 20.0;
|
||||
|
||||
pub const GRAVITY: f32 = 25.0;
|
||||
|
@ -158,6 +158,7 @@ impl State {
|
||||
ecs.register::<comp::Shockwave>();
|
||||
ecs.register::<comp::ShockwaveHitEntities>();
|
||||
ecs.register::<comp::BeamSegment>();
|
||||
ecs.register::<comp::Alignment>();
|
||||
|
||||
// Register components send from clients -> server
|
||||
ecs.register::<comp::Controller>();
|
||||
@ -187,7 +188,6 @@ impl State {
|
||||
ecs.register::<comp::Last<comp::Pos>>();
|
||||
ecs.register::<comp::Last<comp::Vel>>();
|
||||
ecs.register::<comp::Last<comp::Ori>>();
|
||||
ecs.register::<comp::Alignment>();
|
||||
ecs.register::<comp::Agent>();
|
||||
ecs.register::<comp::WaypointArea>();
|
||||
ecs.register::<comp::ForceUpdate>();
|
||||
|
@ -400,6 +400,7 @@ impl<'a> PhysicsData<'a> {
|
||||
mass,
|
||||
collider,
|
||||
read.char_states.get(entity),
|
||||
read.is_ridings.get(entity),
|
||||
))
|
||||
})
|
||||
.for_each(
|
||||
@ -411,6 +412,7 @@ impl<'a> PhysicsData<'a> {
|
||||
mass_other,
|
||||
collider_other,
|
||||
char_state_other_maybe,
|
||||
other_is_riding_maybe,
|
||||
)| {
|
||||
let collision_boundary = previous_cache.collision_boundary
|
||||
+ previous_cache_other.collision_boundary;
|
||||
@ -473,7 +475,7 @@ impl<'a> PhysicsData<'a> {
|
||||
*mass,
|
||||
*mass_other,
|
||||
vel,
|
||||
is_riding.is_some(),
|
||||
is_riding.is_some() || other_is_riding_maybe.is_some(),
|
||||
);
|
||||
}
|
||||
},
|
||||
|
@ -4,7 +4,7 @@ use common::{
|
||||
item::{tool::AbilityMap, MaterialStatManifest},
|
||||
ActiveAbilities, Auras, BeamSegment, Body, Buffs, CanBuild, CharacterState, Collider,
|
||||
Combo, Density, Energy, Group, Health, Inventory, Item, LightEmitter, Mass,
|
||||
Ori, Player, Poise, Pos, Scale, Shockwave, SkillSet, Stats, Sticky, Vel,
|
||||
Ori, Player, Poise, Pos, Scale, Shockwave, SkillSet, Stats, Sticky, Vel, Alignment,
|
||||
},
|
||||
uid::Uid,
|
||||
mounting::{Mount, Rider},
|
||||
@ -69,6 +69,8 @@ pub struct TrackedComps<'a> {
|
||||
pub character_state: ReadStorage<'a, CharacterState>,
|
||||
pub shockwave: ReadStorage<'a, Shockwave>,
|
||||
pub beam_segment: ReadStorage<'a, BeamSegment>,
|
||||
pub alignment: ReadStorage<'a, Alignment>,
|
||||
|
||||
pub ability_map: ReadExpect<'a, AbilityMap>,
|
||||
pub msm: ReadExpect<'a, MaterialStatManifest>,
|
||||
}
|
||||
@ -180,6 +182,10 @@ impl<'a> TrackedComps<'a> {
|
||||
.get(entity)
|
||||
.cloned()
|
||||
.map(|c| comps.push(c.into()));
|
||||
self.alignment
|
||||
.get(entity)
|
||||
.cloned()
|
||||
.map(|c| comps.push(c.into()));
|
||||
// Add untracked comps
|
||||
pos.map(|c| comps.push(c.into()));
|
||||
vel.map(|c| comps.push(c.into()));
|
||||
@ -217,6 +223,7 @@ pub struct ReadTrackers<'a> {
|
||||
pub character_state: ReadExpect<'a, UpdateTracker<CharacterState>>,
|
||||
pub shockwave: ReadExpect<'a, UpdateTracker<Shockwave>>,
|
||||
pub beam_segment: ReadExpect<'a, UpdateTracker<BeamSegment>>,
|
||||
pub alignment: ReadExpect<'a, UpdateTracker<Alignment>>,
|
||||
}
|
||||
impl<'a> ReadTrackers<'a> {
|
||||
pub fn create_sync_packages(
|
||||
@ -268,7 +275,8 @@ impl<'a> ReadTrackers<'a> {
|
||||
filter,
|
||||
)
|
||||
.with_component(&comps.uid, &*self.shockwave, &comps.shockwave, filter)
|
||||
.with_component(&comps.uid, &*self.beam_segment, &comps.beam_segment, filter);
|
||||
.with_component(&comps.uid, &*self.beam_segment, &comps.beam_segment, filter)
|
||||
.with_component(&comps.uid, &*self.alignment, &comps.alignment, filter);
|
||||
|
||||
(entity_sync_package, comp_sync_package)
|
||||
}
|
||||
@ -303,6 +311,7 @@ pub struct WriteTrackers<'a> {
|
||||
character_state: WriteExpect<'a, UpdateTracker<CharacterState>>,
|
||||
shockwave: WriteExpect<'a, UpdateTracker<Shockwave>>,
|
||||
beam: WriteExpect<'a, UpdateTracker<BeamSegment>>,
|
||||
alignment: WriteExpect<'a, UpdateTracker<Alignment>>,
|
||||
}
|
||||
|
||||
fn record_changes(comps: &TrackedComps, trackers: &mut WriteTrackers) {
|
||||
@ -338,6 +347,7 @@ fn record_changes(comps: &TrackedComps, trackers: &mut WriteTrackers) {
|
||||
.record_changes(&comps.character_state);
|
||||
trackers.shockwave.record_changes(&comps.shockwave);
|
||||
trackers.beam.record_changes(&comps.beam_segment);
|
||||
trackers.alignment.record_changes(&comps.alignment);
|
||||
// Debug how many updates are being sent
|
||||
/*
|
||||
macro_rules! log_counts {
|
||||
@ -378,6 +388,7 @@ fn record_changes(comps: &TrackedComps, trackers: &mut WriteTrackers) {
|
||||
log_counts!(character_state, "Character States");
|
||||
log_counts!(shockwave, "Shockwaves");
|
||||
log_counts!(beam, "Beams");
|
||||
log_counts!(alignment, "Alignments");
|
||||
*/
|
||||
}
|
||||
|
||||
@ -409,6 +420,7 @@ pub fn register_trackers(world: &mut World) {
|
||||
world.register_tracker::<CharacterState>();
|
||||
world.register_tracker::<Shockwave>();
|
||||
world.register_tracker::<BeamSegment>();
|
||||
world.register_tracker::<Alignment>();
|
||||
}
|
||||
|
||||
/// Deleted entities grouped by region
|
||||
|
@ -90,6 +90,8 @@ use common::{
|
||||
uid::Uid,
|
||||
util::{srgba_to_linear, Dir},
|
||||
vol::RectRasterableVol,
|
||||
mounting::Mount,
|
||||
link::Is,
|
||||
};
|
||||
use common_base::{prof_span, span};
|
||||
use common_net::{
|
||||
@ -1140,6 +1142,8 @@ impl Hud {
|
||||
let entities = ecs.entities();
|
||||
let me = client.entity();
|
||||
let poises = ecs.read_storage::<comp::Poise>();
|
||||
let alignments = ecs.read_storage::<comp::Alignment>();
|
||||
let is_mount = ecs.read_storage::<Is<Mount>>();
|
||||
|
||||
// Check if there was a persistence load error of the skillset, and if so
|
||||
// display a dialog prompt
|
||||
@ -1664,7 +1668,7 @@ impl Hud {
|
||||
let mut sct_bg_walker = self.ids.sct_bgs.walk();
|
||||
let pulse = self.pulse;
|
||||
|
||||
let make_overitem = |item: &Item, pos, distance, properties, fonts| {
|
||||
let make_overitem = |item: &Item, pos, distance, properties, fonts, interaction_options| {
|
||||
let text = if item.amount() > 1 {
|
||||
format!("{} x {}", item.amount(), item.name())
|
||||
} else {
|
||||
@ -1684,6 +1688,7 @@ impl Hud {
|
||||
properties,
|
||||
pulse,
|
||||
&global_state.window.key_layout,
|
||||
interaction_options,
|
||||
)
|
||||
.x_y(0.0, 100.0)
|
||||
.position_ingame(pos)
|
||||
@ -1714,6 +1719,7 @@ impl Hud {
|
||||
pickup_failed_pulse: self.failed_entity_pickups.get(&entity).copied(),
|
||||
},
|
||||
&self.fonts,
|
||||
vec![(GameInput::Interact, i18n.get("hud.pick_up").to_string())],
|
||||
)
|
||||
.set(overitem_id, ui_widgets);
|
||||
}
|
||||
@ -1733,9 +1739,9 @@ impl Hud {
|
||||
let over_pos = pos + Vec3::unit_z() * 0.7;
|
||||
|
||||
// This is only done once per frame, so it's not a performance issue
|
||||
if block.get_sprite().map_or(false, |s| s.is_container()) {
|
||||
if let Some(sprite) = block.get_sprite().filter(|s| s.is_container()) {
|
||||
overitem::Overitem::new(
|
||||
"???".into(),
|
||||
format!("{:?}", sprite).into(),
|
||||
overitem::TEXT_COLOR,
|
||||
pos.distance_squared(player_pos),
|
||||
&self.fonts,
|
||||
@ -1744,6 +1750,7 @@ impl Hud {
|
||||
overitem_properties,
|
||||
self.pulse,
|
||||
&global_state.window.key_layout,
|
||||
vec![(GameInput::Interact, i18n.get("hud.open").to_string())],
|
||||
)
|
||||
.x_y(0.0, 100.0)
|
||||
.position_ingame(over_pos)
|
||||
@ -1755,6 +1762,7 @@ impl Hud {
|
||||
pos.distance_squared(player_pos),
|
||||
overitem_properties,
|
||||
&self.fonts,
|
||||
vec![(GameInput::Interact, i18n.get("hud.collect").to_string())],
|
||||
)
|
||||
.set(overitem_id, ui_widgets);
|
||||
} else if let Some(desc) = block.get_sprite().and_then(|s| get_sprite_desc(s, i18n))
|
||||
@ -1769,6 +1777,7 @@ impl Hud {
|
||||
overitem_properties,
|
||||
self.pulse,
|
||||
&global_state.window.key_layout,
|
||||
vec![(GameInput::Interact, i18n.get("hud.use").to_string())],
|
||||
)
|
||||
.x_y(0.0, 100.0)
|
||||
.position_ingame(over_pos)
|
||||
@ -1779,7 +1788,7 @@ impl Hud {
|
||||
let speech_bubbles = &self.speech_bubbles;
|
||||
|
||||
// Render overhead name tags and health bars
|
||||
for (pos, info, bubble, _, _, health, _, height_offset, hpfl, in_group) in (
|
||||
for (entity, pos, info, bubble, _, _, health, _, height_offset, hpfl, in_group, dist_sqr, alignment, is_mount) in (
|
||||
&entities,
|
||||
&pos,
|
||||
interpolated.maybe(),
|
||||
@ -1795,6 +1804,7 @@ impl Hud {
|
||||
&inventories,
|
||||
players.maybe(),
|
||||
poises.maybe(),
|
||||
(alignments.maybe(), is_mount.maybe()),
|
||||
)
|
||||
.join()
|
||||
.filter(|t| {
|
||||
@ -1818,6 +1828,7 @@ impl Hud {
|
||||
inventory,
|
||||
player,
|
||||
poise,
|
||||
(alignment, is_mount),
|
||||
)| {
|
||||
// Use interpolated position if available
|
||||
let pos = interpolated.map_or(pos.0, |i| i.pos);
|
||||
@ -1879,6 +1890,7 @@ impl Hud {
|
||||
|
||||
(info.is_some() || bubble.is_some()).then(|| {
|
||||
(
|
||||
entity,
|
||||
pos,
|
||||
info,
|
||||
bubble,
|
||||
@ -1889,6 +1901,9 @@ impl Hud {
|
||||
body.height() * scale.map_or(1.0, |s| s.0) + 0.5,
|
||||
hpfl,
|
||||
in_group,
|
||||
dist_sqr,
|
||||
alignment,
|
||||
is_mount,
|
||||
)
|
||||
})
|
||||
},
|
||||
@ -1911,8 +1926,24 @@ impl Hud {
|
||||
&global_state.settings.interface,
|
||||
self.pulse,
|
||||
i18n,
|
||||
&global_state.settings.controls,
|
||||
&self.imgs,
|
||||
&self.fonts,
|
||||
&global_state.window.key_layout,
|
||||
match alignment {
|
||||
// TODO: Don't use `MAX_MOUNT_RANGE` here, add dedicated interaction range
|
||||
Some(comp::Alignment::Npc) if dist_sqr < common::consts::MAX_MOUNT_RANGE.powi(2)
|
||||
&& interactable.as_ref().and_then(|i| i.entity()) == Some(entity) =>
|
||||
vec![
|
||||
(GameInput::Interact, i18n.get("hud.talk").to_string()),
|
||||
(GameInput::Trade, i18n.get("hud.trade").to_string()),
|
||||
],
|
||||
Some(comp::Alignment::Owned(owner)) if Some(*owner) == client.uid()
|
||||
&& is_mount.is_none()
|
||||
&& dist_sqr < common::consts::MAX_MOUNT_RANGE.powi(2) =>
|
||||
vec![(GameInput::Mount, i18n.get("hud.mount").to_string())],
|
||||
_ => Vec::new(),
|
||||
},
|
||||
)
|
||||
.x_y(0.0, 100.0)
|
||||
.position_ingame(ingame_pos)
|
||||
|
@ -4,15 +4,17 @@ use super::{
|
||||
TEXT_BG, TEXT_COLOR,
|
||||
};
|
||||
use crate::{
|
||||
game_input::GameInput,
|
||||
hud::{get_buff_image, get_buff_info},
|
||||
settings::InterfaceSettings,
|
||||
settings::{ControlSettings, InterfaceSettings},
|
||||
ui::{fonts::Fonts, Ingameable},
|
||||
};
|
||||
use keyboard_keynames::key_layout::KeyLayout;
|
||||
use common::comp::{Buffs, Energy, Health, SpeechBubble, SpeechBubbleType};
|
||||
use conrod_core::{
|
||||
color,
|
||||
position::Align,
|
||||
widget::{self, Image, Rectangle, Text},
|
||||
widget::{self, Image, Rectangle, Text, RoundedRectangle},
|
||||
widget_ids, Color, Colorable, Positionable, Sizeable, Widget, WidgetCommon,
|
||||
};
|
||||
use i18n::Localization;
|
||||
@ -53,6 +55,10 @@ widget_ids! {
|
||||
buffs_align,
|
||||
buffs[],
|
||||
buff_timers[],
|
||||
|
||||
// Interaction hints
|
||||
interaction_hints,
|
||||
interaction_hints_bg,
|
||||
}
|
||||
}
|
||||
|
||||
@ -84,8 +90,11 @@ pub struct Overhead<'a> {
|
||||
settings: &'a InterfaceSettings,
|
||||
pulse: f32,
|
||||
i18n: &'a Localization,
|
||||
controls: &'a ControlSettings,
|
||||
imgs: &'a Imgs,
|
||||
fonts: &'a Fonts,
|
||||
key_layout: &'a Option<KeyLayout>,
|
||||
interaction_options: Vec<(GameInput, String)>,
|
||||
|
||||
#[conrod(common_builder)]
|
||||
common: widget::CommonBuilder,
|
||||
@ -99,8 +108,11 @@ impl<'a> Overhead<'a> {
|
||||
settings: &'a InterfaceSettings,
|
||||
pulse: f32,
|
||||
i18n: &'a Localization,
|
||||
controls: &'a ControlSettings,
|
||||
imgs: &'a Imgs,
|
||||
fonts: &'a Fonts,
|
||||
key_layout: &'a Option<KeyLayout>,
|
||||
interaction_options: Vec<(GameInput, String)>,
|
||||
) -> Self {
|
||||
Self {
|
||||
info,
|
||||
@ -109,8 +121,11 @@ impl<'a> Overhead<'a> {
|
||||
settings,
|
||||
pulse,
|
||||
i18n,
|
||||
controls,
|
||||
imgs,
|
||||
fonts,
|
||||
key_layout,
|
||||
interaction_options,
|
||||
common: widget::CommonBuilder::default(),
|
||||
}
|
||||
}
|
||||
@ -157,6 +172,7 @@ impl<'a> Ingameable for Overhead<'a> {
|
||||
} else {
|
||||
0
|
||||
}
|
||||
+ (!self.interaction_options.is_empty()) as usize * 2
|
||||
}) + if self.bubble.is_some() { 13 } else { 0 }
|
||||
}
|
||||
}
|
||||
@ -448,6 +464,55 @@ impl<'a> Widget for Overhead<'a> {
|
||||
},
|
||||
_ => {},
|
||||
}
|
||||
|
||||
// Interaction hints
|
||||
if !self.interaction_options.is_empty() {
|
||||
let text = self.interaction_options
|
||||
.iter()
|
||||
.filter_map(|(input, action)| Some((self
|
||||
.controls
|
||||
.get_binding(*input)?, action)))
|
||||
.map(|(input, action)| format!("{} {}", input.display_string(self.key_layout).as_str(), action))
|
||||
.collect::<Vec<_>>()
|
||||
.join("\n");
|
||||
|
||||
let scale = 30.0;
|
||||
let btn_rect_size = scale * 0.8;
|
||||
let btn_font_size = scale * 0.6;
|
||||
let btn_rect_pos_y = 0.0;
|
||||
let btn_text_pos_y = btn_rect_pos_y + ((btn_rect_size - btn_font_size) * 0.5);
|
||||
let btn_radius = btn_rect_size / 5.0;
|
||||
let btn_color = Color::Rgba(0.0, 0.0, 0.0, 0.8);
|
||||
|
||||
// RoundedRectangle::fill_with([btn_rect_size, btn_rect_size], btn_radius, btn_color)
|
||||
// .x_y(0.0, btn_rect_pos_y)
|
||||
// .depth(self.distance_from_player_sqr + 2.0)
|
||||
// .parent(id)
|
||||
// .set(state.ids.btn_bg, ui);
|
||||
let hints_text = Text::new(&text)
|
||||
.font_id(self.fonts.cyri.conrod_id)
|
||||
.font_size(btn_font_size as u32)
|
||||
.color(TEXT_COLOR)
|
||||
.parent(id)
|
||||
.down_from(self.info.map_or(state.ids.name, |info| if info.health.map_or(false, should_show_healthbar) {
|
||||
if info.energy.is_some() { state.ids.mana_bar } else { state.ids.health_bar }
|
||||
} else {
|
||||
state.ids.name
|
||||
}), 12.0)
|
||||
.align_middle_x_of(state.ids.name)
|
||||
.depth(1.0);
|
||||
|
||||
let [w, h] = hints_text.get_wh(ui).unwrap_or([btn_rect_size; 2]);
|
||||
|
||||
hints_text.set(state.ids.interaction_hints, ui);
|
||||
|
||||
RoundedRectangle::fill_with([w + btn_radius * 2.0, h + btn_radius * 2.0], btn_radius, btn_color)
|
||||
.depth(2.0)
|
||||
.middle_of(state.ids.interaction_hints)
|
||||
.align_middle_y_of(state.ids.interaction_hints)
|
||||
.parent(id)
|
||||
.set(state.ids.interaction_hints_bg, ui);
|
||||
}
|
||||
}
|
||||
// Speech bubble
|
||||
if let Some(bubble) = self.bubble {
|
||||
|
@ -6,7 +6,7 @@ use crate::{
|
||||
use conrod_core::{
|
||||
color,
|
||||
widget::{self, RoundedRectangle, Text},
|
||||
widget_ids, Color, Colorable, Positionable, Widget, WidgetCommon,
|
||||
widget_ids, Color, Colorable, Positionable, Widget, WidgetCommon, Sizeable,
|
||||
};
|
||||
use i18n::Localization;
|
||||
use std::borrow::Cow;
|
||||
@ -21,7 +21,7 @@ widget_ids! {
|
||||
// Name
|
||||
name_bg,
|
||||
name,
|
||||
// Key
|
||||
// Interaction hints
|
||||
btn_bg,
|
||||
btn,
|
||||
// Inventory full
|
||||
@ -45,6 +45,7 @@ pub struct Overitem<'a> {
|
||||
properties: OveritemProperties,
|
||||
pulse: f32,
|
||||
key_layout: &'a Option<KeyLayout>,
|
||||
interaction_options: Vec<(GameInput, String)>,
|
||||
}
|
||||
|
||||
impl<'a> Overitem<'a> {
|
||||
@ -58,6 +59,7 @@ impl<'a> Overitem<'a> {
|
||||
properties: OveritemProperties,
|
||||
pulse: f32,
|
||||
key_layout: &'a Option<KeyLayout>,
|
||||
interaction_options: Vec<(GameInput, String)>,
|
||||
) -> Self {
|
||||
Self {
|
||||
name,
|
||||
@ -70,6 +72,7 @@ impl<'a> Overitem<'a> {
|
||||
properties,
|
||||
pulse,
|
||||
key_layout,
|
||||
interaction_options,
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -120,7 +123,7 @@ impl<'a> Widget for Overitem<'a> {
|
||||
fn update(self, args: widget::UpdateArgs<Self>) -> Self::Event {
|
||||
let widget::UpdateArgs { id, state, ui, .. } = args;
|
||||
|
||||
let btn_color = Color::Rgba(0.0, 0.0, 0.0, 0.4);
|
||||
let btn_color = Color::Rgba(0.0, 0.0, 0.0, 0.8);
|
||||
|
||||
// Example:
|
||||
// MUSHROOM
|
||||
@ -167,25 +170,35 @@ impl<'a> Widget for Overitem<'a> {
|
||||
.parent(id)
|
||||
.set(state.ids.name, ui);
|
||||
|
||||
// Pickup Button
|
||||
if let Some(key_button) = self
|
||||
.controls
|
||||
.get_binding(GameInput::Interact)
|
||||
.filter(|_| self.properties.active)
|
||||
{
|
||||
RoundedRectangle::fill_with([btn_rect_size, btn_rect_size], btn_radius, btn_color)
|
||||
.x_y(0.0, btn_rect_pos_y)
|
||||
.depth(self.distance_from_player_sqr + 1.0)
|
||||
.parent(id)
|
||||
.set(state.ids.btn_bg, ui);
|
||||
Text::new(key_button.display_string(self.key_layout).as_str())
|
||||
// Interaction hints
|
||||
if !self.interaction_options.is_empty() {
|
||||
let text = self.interaction_options
|
||||
.iter()
|
||||
.filter_map(|(input, action)| Some((self
|
||||
.controls
|
||||
.get_binding(*input)
|
||||
.filter(|_| self.properties.active)?, action)))
|
||||
.map(|(input, action)| format!("{} {}", input.display_string(self.key_layout).as_str(), action))
|
||||
.collect::<Vec<_>>()
|
||||
.join("\n");
|
||||
|
||||
let hints_text = Text::new(&text)
|
||||
.font_id(self.fonts.cyri.conrod_id)
|
||||
.font_size(btn_font_size as u32)
|
||||
.color(TEXT_COLOR)
|
||||
.x_y(0.0, btn_text_pos_y)
|
||||
.depth(self.distance_from_player_sqr + 1.0)
|
||||
.parent(id);
|
||||
|
||||
let [w, h] = hints_text.get_wh(ui).unwrap_or([btn_rect_size; 2]);
|
||||
|
||||
hints_text.set(state.ids.btn, ui);
|
||||
|
||||
RoundedRectangle::fill_with([w + btn_radius * 2.0, h + btn_radius * 2.0], btn_radius, btn_color)
|
||||
.x_y(0.0, btn_rect_pos_y)
|
||||
.depth(self.distance_from_player_sqr + 2.0)
|
||||
.parent(id)
|
||||
.set(state.ids.btn, ui);
|
||||
.set(state.ids.btn_bg, ui);
|
||||
}
|
||||
if let Some(time) = self.properties.pickup_failed_pulse {
|
||||
//should never exceed 1.0, but just in case
|
||||
|
Loading…
Reference in New Issue
Block a user