assets update

acacia trees
updated help.png
bigger map zone name
npc levels from 0-10
boss levels from 20-50
This commit is contained in:
Monty Marz 2019-12-30 12:16:35 +00:00
parent cec303a3c6
commit 8aff5faa83
54 changed files with 498 additions and 118 deletions

View File

@ -23,6 +23,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Added ability to jump while underwater - Added ability to jump while underwater
- Added proper SFX system - Added proper SFX system
- Added changelog - Added changelog
- Added animated Map and Minimap position indicator
- Added visuals to indicate strength compared to the player
### Changed ### Changed
@ -44,6 +46,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Fixed cloud performance - Fixed cloud performance
- Fixed region display name - Fixed region display name
- Fixed the bow fire rate - Fixed the bow fire rate
- Healthbars now flash on critical health
### Removed ### Removed

View File

@ -14,7 +14,7 @@ members = [
# default profile for devs, fast to compile, okay enough to run, no debug information # default profile for devs, fast to compile, okay enough to run, no debug information
[profile.dev] [profile.dev]
opt-level = 2 opt-level = 2
overflow-checks = true overflow-checks = false
debug-assertions = true debug-assertions = true
panic = "abort" panic = "abort"
debug = false debug = false

View File

@ -0,0 +1,8 @@
Item(
name: "Crude Mallet",
description: "Breaks bones like sticks and stones.",
kind: Tool(
kind: Hammer,
power: 20,
),
)

View File

@ -0,0 +1,8 @@
Item(
name: "Humble Stick",
description: "Walking stick with a sharpened end.",
kind: Tool(
kind: Hammer,
power: 6,
),
)

View File

@ -3,6 +3,6 @@ Item(
description: "Every dent tells the story of a chopped tree.", description: "Every dent tells the story of a chopped tree.",
kind: Tool( kind: Tool(
kind: Axe, kind: Axe,
power: 10, power: 15,
), ),
) )

View File

@ -3,6 +3,6 @@ Item(
description: "Someone carved his initials into it...", description: "Someone carved his initials into it...",
kind: Tool( kind: Tool(
kind: Bow, kind: Bow,
power: 10, power: 15,
), ),
) )

View File

@ -3,6 +3,6 @@ Item(
description: "Great for cutting meat.", description: "Great for cutting meat.",
kind: Tool( kind: Tool(
kind: Dagger, kind: Dagger,
power: 10, power: 15,
), ),
) )

View File

@ -3,6 +3,6 @@ Item(
description: "'Property of...' The rest is missing. ", description: "'Property of...' The rest is missing. ",
kind: Tool( kind: Tool(
kind: Hammer, kind: Hammer,
power: 10, power: 15,
), ),
) )

View File

@ -3,6 +3,6 @@ Item(
description: "Smells like resin and magic.", description: "Smells like resin and magic.",
kind: Tool( kind: Tool(
kind: Staff, kind: Staff,
power: 10, power: 20,
), ),
) )

View File

@ -3,6 +3,6 @@ Item(
description: "Held together by Rust and hope.", description: "Held together by Rust and hope.",
kind: Tool( kind: Tool(
kind: Sword, kind: Sword,
power: 10, power: 15,
), ),
) )

Binary file not shown.

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

Binary file not shown.

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

Binary file not shown.

BIN
assets/voxygen/element/buttons/min_plus/mmap_button-min.vox (Stored with Git LFS) Normal file

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
assets/voxygen/element/buttons/min_plus/mmap_button-plus.vox (Stored with Git LFS) Normal file

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
assets/voxygen/element/frames/enemybar.vox (Stored with Git LFS) Normal file

Binary file not shown.

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

Binary file not shown.

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

Binary file not shown.

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

Binary file not shown.

BIN
assets/voxygen/voxel/armor/back/short-0.vox (Stored with Git LFS) Normal file

Binary file not shown.

BIN
assets/voxygen/voxel/npc/oger/belt.vox (Stored with Git LFS) Normal file

Binary file not shown.

BIN
assets/voxygen/voxel/npc/oger/chest.vox (Stored with Git LFS) Normal file

Binary file not shown.

BIN
assets/voxygen/voxel/npc/oger/foot.vox (Stored with Git LFS) Normal file

Binary file not shown.

BIN
assets/voxygen/voxel/npc/oger/hand-l.vox (Stored with Git LFS) Normal file

Binary file not shown.

BIN
assets/voxygen/voxel/npc/oger/hand-r.vox (Stored with Git LFS) Normal file

Binary file not shown.

BIN
assets/voxygen/voxel/npc/oger/head.vox (Stored with Git LFS) Normal file

Binary file not shown.

BIN
assets/voxygen/voxel/npc/oger/legs.vox (Stored with Git LFS) Normal file

Binary file not shown.

BIN
assets/voxygen/voxel/npc/oger/shoulder.vox (Stored with Git LFS) Normal file

Binary file not shown.

BIN
assets/voxygen/voxel/weapon/hammer/hammer_1_2h.vox (Stored with Git LFS) Normal file

Binary file not shown.

BIN
assets/voxygen/voxel/weapon/staff/wood-simple.vox (Stored with Git LFS) Normal file

Binary file not shown.

BIN
assets/world/tree/acacia/1.vox (Stored with Git LFS)

Binary file not shown.

BIN
assets/world/tree/acacia/2.vox (Stored with Git LFS)

Binary file not shown.

BIN
assets/world/tree/acacia/3.vox (Stored with Git LFS)

Binary file not shown.

BIN
assets/world/tree/acacia/4.vox (Stored with Git LFS)

Binary file not shown.

BIN
assets/world/tree/acacia/5.vox (Stored with Git LFS)

Binary file not shown.

BIN
assets/world/tree/acacia_savannah/1.vox (Stored with Git LFS) Normal file

Binary file not shown.

BIN
assets/world/tree/acacia_savannah/2.vox (Stored with Git LFS) Normal file

Binary file not shown.

BIN
assets/world/tree/acacia_savannah/3.vox (Stored with Git LFS) Normal file

Binary file not shown.

BIN
assets/world/tree/acacia_savannah/4.vox (Stored with Git LFS) Normal file

Binary file not shown.

BIN
assets/world/tree/acacia_savannah/5.vox (Stored with Git LFS) Normal file

Binary file not shown.

View File

@ -0,0 +1,69 @@
use rand::{seq::SliceRandom, thread_rng};
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub struct Body {
pub head: Head,
pub shoulder: Shoulder,
pub chest: Chest,
pub hand: Hand
pub belt: Belt,
pub pants: Pants,
pub foot: Foot,
}
impl Body {
pub fn random() -> Self {
let mut rng = thread_rng();
Self {
head: *(&ALL_HEADS).choose(&mut rng).unwrap(),
shoulder: *(&ALL_SHOULDERS).choose(&mut rng).unwrap(),
chest: *(&ALL_CHESTS).choose(&mut rng).unwrap(),
hand: *(&ALL_HANDS).choose(&mut rng).unwrap(),
belt: *(&ALL_BELTS).choose(&mut rng).unwrap(),
pants: *(&ALL_PANTS).choose(&mut rng).unwrap(),
foot: *(&ALL_FEET).choose(&mut rng).unwrap(),
}
}
}
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub enum Head {
Default,
}
const ALL_HEADS: [Head; 1] = [Head::Default];
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub enum Shoulder {
Default,
}
const ALL_SHOULDERS: [Shoulder; 1] = [Shoulder::Default];
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub enum Chest {
Default,
}
const ALL_CHESTS: [Chest; 1] = [Chest::Default];
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub enum Hand {
Default,
}
const ALL_HANDS: [Hand; 1] = [Hand::Default];
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub enum Belt {
Default,
}
const ALL_BELTS: [Belt; 1] = [Belt::Default];
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub enum Pants {
Default,
}
const ALL_FEET: [Foot; 1] = [Foot::Default];
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub enum Foot {
Default,
}

View File

@ -109,6 +109,7 @@ impl<'a> System<'a> for Sys {
client.error_state(RequestStateError::Already) client.error_state(RequestStateError::Already)
} }
ClientState::Spectator | ClientState::Character | ClientState::Dead => { ClientState::Spectator | ClientState::Character | ClientState::Dead => {
// TODO: remove position etc here
client.allow_state(ClientState::Registered) client.allow_state(ClientState::Registered)
} }
ClientState::Pending => {} ClientState::Pending => {}

View File

@ -98,10 +98,8 @@ impl<'a> System<'a> for Sys {
for npc in supplement.npcs { for npc in supplement.npcs {
let (mut stats, mut body) = if rand::random() { let (mut stats, mut body) = if rand::random() {
let stats = comp::Stats::new( let stats = comp::Stats::new(
"Humanoid".to_string(), "Traveler".to_string(),
Some(assets::load_expect_cloned( Some(assets::load_expect_cloned("common.items.weapons.staff_1")),
"common.items.weapons.starter_sword",
)),
); );
let body = comp::Body::Humanoid(comp::humanoid::Body::random()); let body = comp::Body::Humanoid(comp::humanoid::Body::random());
(stats, body) (stats, body)
@ -113,20 +111,18 @@ impl<'a> System<'a> for Sys {
let mut scale = 1.0; let mut scale = 1.0;
// TODO: Remove this and implement scaling or level depending on stuff like species instead // TODO: Remove this and implement scaling or level depending on stuff like species instead
stats.level.set_level(rand::thread_rng().gen_range(1, 3)); stats.level.set_level(rand::thread_rng().gen_range(1, 10));
if npc.boss { if npc.boss {
if rand::random::<f32>() < 0.8 { if rand::random::<f32>() < 0.8 {
stats = comp::Stats::new( stats = comp::Stats::new(
"Humanoid".to_string(), "Fearless Wanderer".to_string(),
Some(assets::load_expect_cloned( Some(assets::load_expect_cloned("common.items.weapons.hammer_1")),
"common.items.weapons.starter_sword",
)),
); );
body = comp::Body::Humanoid(comp::humanoid::Body::random()); body = comp::Body::Humanoid(comp::humanoid::Body::random());
} }
stats.level.set_level(rand::thread_rng().gen_range(10, 50)); stats.level.set_level(rand::thread_rng().gen_range(20, 50));
scale = 2.5 + rand::random::<f32>(); scale = 2.0 + rand::random::<f32>();
} }
stats.update_max_hp(); stats.update_max_hp();

View File

@ -118,10 +118,14 @@ image_ids! {
grass: "voxygen.element.icons.item_grass", grass: "voxygen.element.icons.item_grass",
apple: "voxygen.element.icons.item_apple", apple: "voxygen.element.icons.item_apple",
mushroom: "voxygen.element.icons.item_mushroom", mushroom: "voxygen.element.icons.item_mushroom",
skull: "voxygen.element.icons.skull",
skull_2: "voxygen.element.icons.skull_2",
// Map // Map
map_indicator: "voxygen.element.buttons.map_indicator", map_indicator: "voxygen.element.buttons.map_indicator",
indicator_mmap: "voxygen.element.buttons.indicator_mmap", indicator_mmap: "voxygen.element.buttons.indicator_mmap",
indicator_mmap_2: "voxygen.element.buttons.indicator_mmap_2",
indicator_mmap_3: "voxygen.element.buttons.indicator_mmap_3",
// Crosshair // Crosshair
@ -154,6 +158,12 @@ image_ids! {
mmap_open: "voxygen.element.buttons.button_mmap_open", mmap_open: "voxygen.element.buttons.button_mmap_open",
mmap_open_hover: "voxygen.element.buttons.button_mmap_open_hover", mmap_open_hover: "voxygen.element.buttons.button_mmap_open_hover",
mmap_open_press: "voxygen.element.buttons.button_mmap_open_press", mmap_open_press: "voxygen.element.buttons.button_mmap_open_press",
mmap_plus: "voxygen.element.buttons.min_plus.mmap_button-plus",
mmap_plus_hover: "voxygen.element.buttons.min_plus.mmap_button-plus_hover",
mmap_plus_press: "voxygen.element.buttons.min_plus.mmap_button-plus_hover",
mmap_minus: "voxygen.element.buttons.min_plus.mmap_button-min",
mmap_minus_hover: "voxygen.element.buttons.min_plus.mmap_button-min_hover",
mmap_minus_press: "voxygen.element.buttons.min_plus.mmap_button-min_press",
// Grid // Grid
grid: "voxygen.element.buttons.grid", grid: "voxygen.element.buttons.grid",
@ -221,6 +231,10 @@ image_ids! {
key: "voxygen.voxel.object.key", key: "voxygen.voxel.object.key",
key_gold: "voxygen.voxel.object.key_gold", key_gold: "voxygen.voxel.object.key_gold",
// Enemy Healthbar
enemy_health: "voxygen.element.frames.enemybar",
////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////

View File

@ -5,7 +5,7 @@ use conrod_core::{
color, color,
image::Id, image::Id,
widget::{self, Button, Image, Rectangle, Text}, widget::{self, Button, Image, Rectangle, Text},
widget_ids, Colorable, Positionable, Sizeable, Widget, WidgetCommon, widget_ids, Color, Colorable, Positionable, Sizeable, Widget, WidgetCommon,
}; };
use specs::WorldExt; use specs::WorldExt;
use vek::*; use vek::*;
@ -31,12 +31,12 @@ widget_ids! {
pub struct Map<'a> { pub struct Map<'a> {
_show: &'a Show, _show: &'a Show,
client: &'a Client, client: &'a Client,
_world_map: Id, _world_map: Id,
imgs: &'a Imgs, imgs: &'a Imgs,
fonts: &'a Fonts, fonts: &'a Fonts,
#[conrod(common_builder)] #[conrod(common_builder)]
common: widget::CommonBuilder, common: widget::CommonBuilder,
pulse: f32,
} }
impl<'a> Map<'a> { impl<'a> Map<'a> {
pub fn new( pub fn new(
@ -45,6 +45,7 @@ impl<'a> Map<'a> {
imgs: &'a Imgs, imgs: &'a Imgs,
world_map: Id, world_map: Id,
fonts: &'a Fonts, fonts: &'a Fonts,
pulse: f32,
) -> Self { ) -> Self {
Self { Self {
_show: show, _show: show,
@ -53,6 +54,7 @@ impl<'a> Map<'a> {
client, client,
fonts: fonts, fonts: fonts,
common: widget::CommonBuilder::default(), common: widget::CommonBuilder::default(),
pulse,
} }
} }
} }
@ -129,9 +131,10 @@ impl<'a> Widget for Map<'a> {
// Location Name // Location Name
match self.client.current_chunk() { match self.client.current_chunk() {
Some(chunk) => Text::new(chunk.meta().name()) Some(chunk) => Text::new(chunk.meta().name())
.mid_top_with_margin_on(state.ids.map_bg, 70.0) .mid_top_with_margin_on(state.ids.map_bg, 55.0)
.font_size(20) .font_size(60)
.color(TEXT_COLOR) .color(TEXT_COLOR)
.font_id(self.fonts.alkhemi)
.parent(state.ids.map_frame_r) .parent(state.ids.map_frame_r)
.set(state.ids.location_name, ui), .set(state.ids.location_name, ui),
None => Text::new(" ") None => Text::new(" ")
@ -157,15 +160,33 @@ impl<'a> Widget for Map<'a> {
.map_or(Vec3::zero(), |pos| pos.0); .map_or(Vec3::zero(), |pos| pos.0);
let worldsize = 32768.0; // TODO This has to get the actual world size and not be hardcoded let worldsize = 32768.0; // TODO This has to get the actual world size and not be hardcoded
let x = player_pos.x as f64 / worldsize * 700.0; let x = player_pos.x as f64 / worldsize * 700.0/*= x-Size of the map image*/;
let y = (/*1.0 -*/player_pos.y as f64 / worldsize) * 700.0; let y = (/*1.0 -*/player_pos.y as f64 / worldsize) * 700.0;
let indic_ani = (self.pulse * 6.0/*animation speed*/).cos()/*starts at 1.0*/ * 0.5 + 0.50; // changes the animation frame
let indic_scale = 1.2;
// Indicator // Indicator
Image::new(self.imgs.map_indicator) Image::new(if indic_ani <= 0.3 {
.bottom_left_with_margins_on(state.ids.grid, y, x - (12.0 * 1.4) / 2.0) self.imgs.indicator_mmap
.w_h(12.0 * 1.4, 21.0 * 1.4) } else if indic_ani <= 0.6 {
.floating(true) self.imgs.indicator_mmap_2
.parent(ui.window) } else {
.set(state.ids.indicator, ui); self.imgs.indicator_mmap_3
})
.bottom_left_with_margins_on(state.ids.grid, y, x - (20.0 * 1.2) / 2.0)
.w_h(
22.0 * 1.2,
if indic_ani <= 0.3 {
16.0 * indic_scale
} else if indic_ani <= 0.6 {
23.0 * indic_scale
} else {
34.0 * indic_scale
},
)
.color(Some(Color::Rgba(1.0, 1.0, 1.0, 1.0)))
.floating(true)
.parent(ui.window)
.set(state.ids.indicator, ui);
None None
} }

View File

@ -17,6 +17,8 @@ widget_ids! {
mmap_frame_bg, mmap_frame_bg,
mmap_location, mmap_location,
mmap_button, mmap_button,
mmap_plus,
mmap_minus,
zone_display_bg, zone_display_bg,
zone_display, zone_display,
grid, grid,
@ -35,6 +37,8 @@ pub struct MiniMap<'a> {
fonts: &'a Fonts, fonts: &'a Fonts,
#[conrod(common_builder)] #[conrod(common_builder)]
common: widget::CommonBuilder, common: widget::CommonBuilder,
pulse: f32,
zoom: f32,
} }
impl<'a> MiniMap<'a> { impl<'a> MiniMap<'a> {
@ -44,6 +48,8 @@ impl<'a> MiniMap<'a> {
imgs: &'a Imgs, imgs: &'a Imgs,
world_map: Id, world_map: Id,
fonts: &'a Fonts, fonts: &'a Fonts,
pulse: f32,
zoom: f32,
) -> Self { ) -> Self {
Self { Self {
show, show,
@ -52,6 +58,8 @@ impl<'a> MiniMap<'a> {
_world_map: world_map, _world_map: world_map,
fonts: fonts, fonts: fonts,
common: widget::CommonBuilder::default(), common: widget::CommonBuilder::default(),
pulse,
zoom,
} }
} }
} }
@ -87,20 +95,49 @@ 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 = self.zoom as f64;
if self.show.mini_map { if self.show.mini_map {
Image::new(self.imgs.mmap_frame) Image::new(self.imgs.mmap_frame)
.w_h(100.0 * 4.0, 100.0 * 4.0) .w_h(100.0 * 4.0 * zoom, 100.0 * 4.0 * zoom)
.top_right_with_margins_on(ui.window, 5.0, 5.0) .top_right_with_margins_on(ui.window, 5.0, 5.0)
.set(state.ids.mmap_frame, ui); .set(state.ids.mmap_frame, ui);
Rectangle::fill_with([92.0 * 4.0, 82.0 * 4.0], color::TRANSPARENT) Rectangle::fill_with([92.0 * 4.0, 82.0 * 4.0], color::TRANSPARENT)
.mid_top_with_margin_on(state.ids.mmap_frame, 13.0 * 4.0 + 4.0) .mid_top_with_margin_on(state.ids.mmap_frame, 13.0 * 4.0 + 4.0 * zoom)
.set(state.ids.mmap_frame_bg, ui); .set(state.ids.mmap_frame_bg, ui);
// Zoom Buttons
// TODO: Add zoomable minimap
/*if Button::image(self.imgs.mmap_plus)
.w_h(100.0 * 0.2 * zoom, 100.0 * 0.2 * zoom)
.hover_image(self.imgs.mmap_plus_hover)
.press_image(self.imgs.mmap_plus_press)
.top_left_with_margins_on(state.ids.mmap_frame, 0.0, 0.0)
.set(state.ids.mmap_plus, ui)
.was_clicked()
{
if zoom > 0.0 {
zoom = zoom + 1.0
} else if zoom == 5.0 {
}
}
if Button::image(self.imgs.mmap_minus)
.w_h(100.0 * 0.2 * zoom, 100.0 * 0.2 * zoom)
.hover_image(self.imgs.mmap_minus_hover)
.press_image(self.imgs.mmap_minus_press)
.down_from(state.ids.mmap_plus, 0.0)
.set(state.ids.mmap_minus, ui)
.was_clicked()
{
if zoom < 6.0 {
zoom = zoom - 1.0
} else if zoom == 0.0 {
}
}*/
// Map Image // Map Image
Image::new(/*self.world_map*/ self.imgs.map_placeholder) Image::new(/*self.world_map*/ self.imgs.map_placeholder)
.middle_of(state.ids.mmap_frame_bg) .middle_of(state.ids.mmap_frame_bg)
.w_h(92.0 * 4.0, 82.0 * 4.0) .w_h(92.0 * 4.0 * zoom, 82.0 * 4.0 * zoom)
.parent(state.ids.mmap_frame_bg) .parent(state.ids.mmap_frame_bg)
.set(state.ids.grid, ui); .set(state.ids.grid, ui);
// Coordinates // Coordinates
@ -115,13 +152,28 @@ impl<'a> Widget for MiniMap<'a> {
let worldsize = 32768.0; // TODO This has to get the actual world size and not be hardcoded let worldsize = 32768.0; // TODO This has to get the actual world size and not be hardcoded
let x = player_pos.x as f64 / worldsize * 92.0 * 4.0; let x = player_pos.x as f64 / worldsize * 92.0 * 4.0;
let y = (/*1.0X-*/player_pos.y as f64 / worldsize) * 82.0 * 4.0; let y = (/*1.0X-*/player_pos.y as f64 / worldsize) * 82.0 * 4.0;
let indic_ani = (self.pulse * 6.0).cos() * 0.5 + 0.5; //Animation timer
let indic_scale = 0.8;
// Indicator // Indicator
Image::new(self.imgs.indicator_mmap) Image::new(if indic_ani <= 0.5 {
.bottom_left_with_margins_on(state.ids.grid, y, x - 5.0) self.imgs.indicator_mmap
.w_h(10.0, 10.0) } else {
.floating(true) self.imgs.indicator_mmap_2
.parent(ui.window) })
.set(state.ids.indicator, ui); .bottom_left_with_margins_on(state.ids.grid, y, x - 5.0)
.w_h(
// Animation frames depening on timer value from 0.0 to 1.0
22.0 * 0.8,
if indic_ani <= 0.5 {
18.0 * indic_scale
} else {
23.0 * indic_scale
},
)
.color(Some(Color::Rgba(1.0, 1.0, 1.0, 1.0)))
.floating(true)
.parent(ui.window)
.set(state.ids.indicator, ui);
} else { } else {
Image::new(self.imgs.mmap_frame_closed) Image::new(self.imgs.mmap_frame_closed)
.w_h(100.0 * 2.0, 11.0 * 2.0) .w_h(100.0 * 2.0, 11.0 * 2.0)
@ -137,7 +189,7 @@ impl<'a> Widget for MiniMap<'a> {
.wh(if self.show.mini_map { .wh(if self.show.mini_map {
[100.0 * 0.4; 2] [100.0 * 0.4; 2]
} else { } else {
[100.0 * 0.2; 2] [100.0 * 0.2 * zoom; 2]
}) })
.hover_image(if self.show.mini_map { .hover_image(if self.show.mini_map {
self.imgs.mmap_open_hover self.imgs.mmap_open_hover

View File

@ -14,7 +14,9 @@ mod social;
mod spell; mod spell;
use crate::hud::img_ids::ImgsRot; use crate::hud::img_ids::ImgsRot;
//use rand::Rng;
pub use settings_window::ScaleChange; pub use settings_window::ScaleChange;
use std::time::Duration;
use bag::Bag; use bag::Bag;
use buttons::Buttons; use buttons::Buttons;
@ -64,7 +66,7 @@ const TEXT_COLOR_3: Color = Color::Rgba(1.0, 1.0, 1.0, 0.1);
//const BG_COLOR: Color = Color::Rgba(1.0, 1.0, 1.0, 0.8); //const BG_COLOR: Color = Color::Rgba(1.0, 1.0, 1.0, 0.8);
const HP_COLOR: Color = Color::Rgba(0.33, 0.63, 0.0, 1.0); const HP_COLOR: Color = Color::Rgba(0.33, 0.63, 0.0, 1.0);
const LOW_HP_COLOR: Color = Color::Rgba(0.93, 0.59, 0.03, 1.0); const LOW_HP_COLOR: Color = Color::Rgba(0.93, 0.59, 0.03, 1.0);
const CRITICAL_HP_COLOR: Color = Color::Rgba(1.0, 0.0, 0.0, 1.0); const CRITICAL_HP_COLOR: Color = Color::Rgba(0.79, 0.19, 0.17, 1.0);
const MANA_COLOR: Color = Color::Rgba(0.47, 0.55, 1.0, 0.9); const MANA_COLOR: Color = Color::Rgba(0.47, 0.55, 1.0, 0.9);
//const FOCUS_COLOR: Color = Color::Rgba(1.0, 0.56, 0.04, 1.0); //const 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);
@ -86,8 +88,12 @@ widget_ids! {
// Character Names // Character Names
name_tags[], name_tags[],
levels[],
levels_skull[],
// Health Bars // Health Bars
health_bars[], health_bars[],
mana_bars[],
health_bar_fronts[],
health_bar_backs[], health_bar_backs[],
// Intro Text // Intro Text
@ -410,6 +416,8 @@ pub struct Hud {
force_ungrab: bool, force_ungrab: bool,
force_chat_input: Option<String>, force_chat_input: Option<String>,
force_chat_cursor: Option<Index>, force_chat_cursor: Option<Index>,
pulse: f32,
zoom: f32,
} }
impl Hud { impl Hud {
@ -469,6 +477,8 @@ impl Hud {
force_ungrab: false, force_ungrab: false,
force_chat_input: None, force_chat_input: None,
force_chat_cursor: None, force_chat_cursor: None,
pulse: 0.0,
zoom: 1.0,
} }
} }
@ -477,9 +487,12 @@ impl Hud {
client: &Client, client: &Client,
global_state: &GlobalState, global_state: &GlobalState,
debug_info: DebugInfo, debug_info: DebugInfo,
dt: Duration,
) -> Vec<Event> { ) -> Vec<Event> {
let mut events = Vec::new(); let mut events = Vec::new();
let (ref mut ui_widgets, ref mut tooltip_manager) = self.ui.set_widgets(); let (ref mut ui_widgets, ref mut tooltip_manager) = self.ui.set_widgets();
// pulse time for pulsating elements
self.pulse = self.pulse + dt.as_secs_f32();
let version = format!( let version = format!(
"{}-{}", "{}-{}",
@ -522,6 +535,10 @@ impl Hud {
let entities = ecs.entities(); let entities = ecs.entities();
let me = client.entity(); let me = client.entity();
let view_distance = client.view_distance().unwrap_or(1); let view_distance = client.view_distance().unwrap_or(1);
let own_level = stats
.get(client.entity())
.map_or(0, |stats| stats.level.level());
// Get player position. // Get player position.
let player_pos = client let player_pos = client
.state() .state()
@ -530,8 +547,95 @@ impl Hud {
.get(client.entity()) .get(client.entity())
.map_or(Vec3::zero(), |pos| pos.0); .map_or(Vec3::zero(), |pos| pos.0);
let mut name_id_walker = self.ids.name_tags.walk(); let mut name_id_walker = self.ids.name_tags.walk();
let mut level_id_walker = self.ids.levels.walk();
let mut level_skull_id_walker = self.ids.levels_skull.walk();
let mut health_id_walker = self.ids.health_bars.walk(); let mut health_id_walker = self.ids.health_bars.walk();
let mut mana_id_walker = self.ids.mana_bars.walk();
let mut health_back_id_walker = self.ids.health_bar_backs.walk(); let mut health_back_id_walker = self.ids.health_bar_backs.walk();
let mut health_front_id_walker = self.ids.health_bar_fronts.walk();
// Render Health Bars
for (_entity, pos, stats, scale) in (&entities, &pos, &stats, scales.maybe())
.join()
.filter(|(entity, _, stats, _)| {
*entity != me && !stats.is_dead
//&& stats.health.current() != stats.health.maximum()
})
// Don't process health bars outside the vd (visibility further limited by ui backend)
.filter(|(_, pos, _, _)| {
Vec2::from(pos.0 - player_pos)
.map2(TerrainChunk::RECT_SIZE, |d: f32, sz| {
d.abs() as f32 / sz as f32
})
.magnitude()
< view_distance as f32
})
{
let scale = scale.map(|s| s.0).unwrap_or(1.0);
let back_id = health_back_id_walker.next(
&mut self.ids.health_bar_backs,
&mut ui_widgets.widget_id_generator(),
);
let health_bar_id = health_id_walker.next(
&mut self.ids.health_bars,
&mut ui_widgets.widget_id_generator(),
);
let mana_bar_id = mana_id_walker.next(
&mut self.ids.mana_bars,
&mut ui_widgets.widget_id_generator(),
);
let front_id = health_front_id_walker.next(
&mut self.ids.health_bar_fronts,
&mut ui_widgets.widget_id_generator(),
);
let hp_percentage =
stats.health.current() as f64 / stats.health.maximum() as f64 * 100.0;
let hp_ani = (self.pulse * 4.0/*speed factor*/).cos() * 0.5 + 1.0; //Animation timer
let crit_hp_color: Color = Color::Rgba(0.79, 0.19, 0.17, hp_ani);
// Background
Rectangle::fill_with([82.0, 8.0], Color::Rgba(0.3, 0.3, 0.3, 0.5))
.x_y(0.0, -25.0)
.position_ingame(pos.0 + Vec3::new(0.0, 0.0, 1.5 * scale + 1.5))
.resolution(100.0)
.set(back_id, ui_widgets);
// % HP Filling
Image::new(self.imgs.bar_content)
.w_h(72.9 * (hp_percentage / 100.0), 5.9)
.x_y(4.5, -24.0)
.color(Some(if hp_percentage <= 25.0 {
crit_hp_color
} else if hp_percentage <= 50.0 {
LOW_HP_COLOR
} else {
HP_COLOR
}))
.position_ingame(pos.0 + Vec3::new(0.0, 0.0, 1.5 * scale + 1.5))
.resolution(100.0)
.set(health_bar_id, ui_widgets);
// % Mana Filling
Rectangle::fill_with(
[
73.0 * (stats.energy.current() as f64 / stats.energy.maximum() as f64),
1.5,
],
MANA_COLOR,
)
.x_y(4.5, -28.0)
.position_ingame(pos.0 + Vec3::new(0.0, 0.0, 1.5 * scale + 1.5))
.resolution(100.0)
.set(mana_bar_id, ui_widgets);
// Foreground
Image::new(self.imgs.enemy_health)
.w_h(84.0, 10.0)
.x_y(0.0, -25.0)
.color(Some(Color::Rgba(1.0, 1.0, 1.0, 0.99)))
.position_ingame(pos.0 + Vec3::new(0.0, 0.0, 1.5 * scale + 1.5))
.resolution(100.0)
.set(front_id, ui_widgets);
}
// Render Name Tags // Render Name Tags
for (pos, name, level, scale) in for (pos, name, level, scale) in
@ -558,69 +662,71 @@ impl Hud {
(pos.0, name, stats.level, scale) (pos.0, name, stats.level, scale)
}) })
{ {
let info = format!("{} Level {}", name, level.level()); let name = format!("{}", name);
let scale = scale.map(|s| s.0).unwrap_or(1.0); let scale = scale.map(|s| s.0).unwrap_or(1.0);
let name_id = name_id_walker.next(
let id = name_id_walker.next(
&mut self.ids.name_tags, &mut self.ids.name_tags,
&mut ui_widgets.widget_id_generator(), &mut ui_widgets.widget_id_generator(),
); );
Text::new(&info) let level_id = level_id_walker
.next(&mut self.ids.levels, &mut ui_widgets.widget_id_generator());
let level_skull_id = level_skull_id_walker.next(
&mut self.ids.levels_skull,
&mut ui_widgets.widget_id_generator(),
);
// Name
Text::new(&name)
.font_size(20) .font_size(20)
.color(Color::Rgba(0.61, 0.61, 0.89, 1.0)) .color(Color::Rgba(0.61, 0.61, 0.89, 1.0))
.x_y(0.0, 0.0) .x_y(0.0, 0.0)
.position_ingame(pos + Vec3::new(0.0, 0.0, 1.5 * scale + 1.5)) .position_ingame(pos + Vec3::new(0.0, 0.0, 1.5 * scale + 1.5))
.resolution(100.0) .resolution(100.0)
.set(id, ui_widgets); .set(name_id, ui_widgets);
}
// Render Health Bars // Level
for (_entity, pos, stats, scale) in (&entities, &pos, &stats, scales.maybe()) const LOW: Color = Color::Rgba(0.54, 0.81, 0.94, 0.4);
.join() const HIGH: Color = Color::Rgba(1.0, 0.0, 0.0, 1.0);
.filter(|(entity, _, stats, _)| { const EQUAL: Color = Color::Rgba(1.0, 1.0, 1.0, 1.0);
*entity != me let op_level = level.level();
&& !stats.is_dead let level_str = format!("{}", op_level);
&& stats.health.current() != stats.health.maximum() // Change visuals of the level display depending on the player level/opponent level
}) let level_comp = op_level as i64 - own_level as i64;
// Don't process health bars outside the vd (visibility further limited by ui backend) // + 10 level above player -> skull
.filter(|(_, pos, _, _)| { // + 5-10 levels above player -> high
Vec2::from(pos.0 - player_pos) // -5 - +5 levels around player level -> equal
.map2(TerrainChunk::RECT_SIZE, |d: f32, sz| { // - 5 levels below player -> low
d.abs() as f32 / sz as f32 Text::new(if level_comp < 10 { &level_str } else { "?" })
}) .font_size(if op_level > 9 && level_comp < 10 {
.magnitude() 7
< view_distance as f32 } else {
}) 8
{ })
let scale = scale.map(|s| s.0).unwrap_or(1.0); .color(if level_comp > 4 {
HIGH
let back_id = health_back_id_walker.next( } else if level_comp < -5 {
&mut self.ids.health_bar_backs, LOW
&mut ui_widgets.widget_id_generator(), } else {
); EQUAL
let bar_id = health_id_walker.next( })
&mut self.ids.health_bars, .x_y(-37.0, -24.0)
&mut ui_widgets.widget_id_generator(), .position_ingame(pos + Vec3::new(0.0, 0.0, 1.5 * scale + 1.5))
);
// Background
Rectangle::fill_with([120.0, 8.0], Color::Rgba(0.3, 0.3, 0.3, 0.5))
.x_y(0.0, -25.0)
.position_ingame(pos.0 + Vec3::new(0.0, 0.0, 1.5 * scale + 1.5))
.resolution(100.0) .resolution(100.0)
.set(back_id, ui_widgets); .set(level_id, ui_widgets);
if level_comp > 9 {
// % HP Filling let skull_ani = ((self.pulse * 0.7/*speed factor*/).cos() * 0.5 + 0.5) * 10.0; //Animation timer
Rectangle::fill_with( Image::new(if skull_ani as i32 == 1 && rand::random::<f32>() < 0.9 {
[ self.imgs.skull_2
120.0 * (stats.health.current() as f64 / stats.health.maximum() as f64), } else {
8.0, self.imgs.skull
], })
HP_COLOR, .w_h(30.0, 30.0)
) .x_y(0.0, 24.0)
.x_y(0.0, -25.0) .color(Some(Color::Rgba(1.0, 1.0, 1.0, 0.8)))
.position_ingame(pos.0 + Vec3::new(0.0, 0.0, 1.5 * scale + 1.5)) .position_ingame(pos + Vec3::new(0.0, 0.0, 1.5 * scale + 1.5))
.resolution(100.0) .resolution(100.0)
.set(bar_id, ui_widgets); .set(level_skull_id, ui_widgets);
}
} }
} }
// Introduction Text // Introduction Text
@ -915,7 +1021,7 @@ impl Hud {
if self.show.help && !self.show.map && !self.show.esc_menu { if self.show.help && !self.show.map && !self.show.esc_menu {
Image::new(self.imgs.help) Image::new(self.imgs.help)
.middle_of(ui_widgets.window) .middle_of(ui_widgets.window)
.w_h(1260.0, 519.0) .w_h(1260.0 * 1.2, 519.0 * 1.2)
.set(self.ids.help, ui_widgets); .set(self.ids.help, ui_widgets);
// Show tips // Show tips
if Button::image(self.imgs.button) if Button::image(self.imgs.button)
@ -969,8 +1075,16 @@ impl Hud {
} }
// MiniMap // MiniMap
match MiniMap::new(&self.show, client, &self.imgs, self.world_map, &self.fonts) match MiniMap::new(
.set(self.ids.minimap, ui_widgets) &self.show,
client,
&self.imgs,
self.world_map,
&self.fonts,
self.pulse,
self.zoom,
)
.set(self.ids.minimap, ui_widgets)
{ {
Some(minimap::Event::Toggle) => self.show.toggle_mini_map(), Some(minimap::Event::Toggle) => self.show.toggle_mini_map(),
None => {} None => {}
@ -1005,7 +1119,7 @@ impl Hud {
.read_storage::<comp::Stats>() .read_storage::<comp::Stats>()
.get(client.entity()) .get(client.entity())
{ {
Skillbar::new(global_state, &self.imgs, &self.fonts, stats) Skillbar::new(global_state, &self.imgs, &self.fonts, &stats, self.pulse)
.set(self.ids.skillbar, ui_widgets); .set(self.ids.skillbar, ui_widgets);
} }
@ -1169,8 +1283,15 @@ impl Hud {
} }
// Map // Map
if self.show.map { if self.show.map {
match Map::new(&self.show, client, &self.imgs, self.world_map, &self.fonts) match Map::new(
.set(self.ids.map, ui_widgets) &self.show,
client,
&self.imgs,
self.world_map,
&self.fonts,
self.pulse,
)
.set(self.ids.map, ui_widgets)
{ {
Some(map::Event::Close) => { Some(map::Event::Close) => {
self.show.map(false); self.show.map(false);
@ -1354,11 +1475,12 @@ impl Hud {
global_state: &mut GlobalState, global_state: &mut GlobalState,
debug_info: DebugInfo, debug_info: DebugInfo,
camera: &Camera, camera: &Camera,
dt: Duration,
) -> Vec<Event> { ) -> Vec<Event> {
if let Some(maybe_id) = self.to_focus.take() { if let Some(maybe_id) = self.to_focus.take() {
self.ui.focus_widget(maybe_id); self.ui.focus_widget(maybe_id);
} }
let events = self.update_layout(client, global_state, debug_info); let events = self.update_layout(client, global_state, debug_info, dt);
let (view_mat, _, _) = camera.compute_dependents(client); let (view_mat, _, _) = camera.compute_dependents(client);
let fov = camera.get_fov(); let fov = camera.get_fov();
self.ui.maintain( self.ui.maintain(

View File

@ -451,7 +451,7 @@ impl<'a> Widget for SettingsWindow<'a> {
if let Some(new_val) = ImageSlider::continuous( if let Some(new_val) = ImageSlider::continuous(
scale.log(2.0), scale.log(2.0),
0.5f64.log(2.0), 0.5f64.log(2.0),
1.2f64.log(2.0), 1.0f64.log(2.0),
self.imgs.slider_indicator, self.imgs.slider_indicator,
self.imgs.slider, self.imgs.slider,
) )
@ -857,7 +857,7 @@ impl<'a> Widget for SettingsWindow<'a> {
{ {
events.push(Event::ChatTransp(new_val)); events.push(Event::ChatTransp(new_val));
} }
Rectangle::fill_with([40.0 * 4.0, 1.0 * 4.0], color::TRANSPARENT) Rectangle::fill_with([60.0 * 4.0, 1.0 * 4.0], color::TRANSPARENT)
.down_from(state.ids.chat_transp_title, 30.0) .down_from(state.ids.chat_transp_title, 30.0)
.set(state.ids.placeholder, ui); .set(state.ids.placeholder, ui);
} }

View File

@ -92,6 +92,7 @@ pub struct Skillbar<'a> {
imgs: &'a Imgs, imgs: &'a Imgs,
fonts: &'a Fonts, fonts: &'a Fonts,
stats: &'a Stats, stats: &'a Stats,
pulse: f32,
#[conrod(common_builder)] #[conrod(common_builder)]
common: widget::CommonBuilder, common: widget::CommonBuilder,
current_resource: ResourceType, current_resource: ResourceType,
@ -103,6 +104,7 @@ impl<'a> Skillbar<'a> {
imgs: &'a Imgs, imgs: &'a Imgs,
fonts: &'a Fonts, fonts: &'a Fonts,
stats: &'a Stats, stats: &'a Stats,
pulse: f32,
) -> Self { ) -> Self {
Self { Self {
imgs, imgs,
@ -111,6 +113,7 @@ impl<'a> Skillbar<'a> {
global_state, global_state,
current_resource: ResourceType::Mana, current_resource: ResourceType::Mana,
common: widget::CommonBuilder::default(), common: widget::CommonBuilder::default(),
pulse,
} }
} }
} }
@ -164,6 +167,8 @@ impl<'a> Widget for Skillbar<'a> {
const BG_COLOR: Color = Color::Rgba(1.0, 1.0, 1.0, 0.8); const BG_COLOR: Color = Color::Rgba(1.0, 1.0, 1.0, 0.8);
const BG_COLOR_2: Color = Color::Rgba(0.0, 0.0, 0.0, 0.99); const BG_COLOR_2: Color = Color::Rgba(0.0, 0.0, 0.0, 0.99);
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);
// Stamina Wheel // Stamina Wheel
/* /*
@ -300,7 +305,6 @@ impl<'a> Widget for Skillbar<'a> {
.top_left_with_margins_on(state.ids.xp_bar_left, 2.0 * scale, 10.0 * scale) .top_left_with_margins_on(state.ids.xp_bar_left, 2.0 * scale, 10.0 * scale)
.set(state.ids.xp_bar_filling, ui); .set(state.ids.xp_bar_filling, ui);
// Level Display // Level Display
if self.stats.level.level() < 10 { if self.stats.level.level() < 10 {
Text::new(&level) Text::new(&level)
.bottom_left_with_margins_on( .bottom_left_with_margins_on(
@ -777,7 +781,7 @@ impl<'a> Widget for Skillbar<'a> {
Image::new(self.imgs.bar_content) Image::new(self.imgs.bar_content)
.w_h(97.0 * scale * hp_percentage / 100.0, 16.0 * scale) .w_h(97.0 * scale * hp_percentage / 100.0, 16.0 * scale)
.color(Some(if hp_percentage <= 20.0 { .color(Some(if hp_percentage <= 20.0 {
CRITICAL_HP_COLOR crit_hp_color
} else if hp_percentage <= 40.0 { } else if hp_percentage <= 40.0 {
LOW_HP_COLOR LOW_HP_COLOR
} else { } else {

View File

@ -389,6 +389,7 @@ impl PlayState for SessionState {
.cloned(), .cloned(),
}, },
&self.scene.camera(), &self.scene.camera(),
clock.get_last_delta(),
); );
// Maintain the UI. // Maintain the UI.