Merge branch 'combat' of https://gitlab.com/veloren/veloren into combat

This commit is contained in:
jshipsey 2020-03-20 18:54:54 -04:00
commit 514d65eb7c
20 changed files with 153 additions and 70 deletions

Binary file not shown.

BIN
assets/voxygen/element/frames/window.vox (Stored with Git LFS)

Binary file not shown.

BIN
assets/voxygen/element/frames/window_3.vox (Stored with Git LFS)

Binary file not shown.

BIN
assets/voxygen/element/frames/window_4.vox (Stored with Git LFS)

Binary file not shown.

BIN
assets/voxygen/element/icons/endurance.png (Stored with Git LFS) Normal file

Binary file not shown.

BIN
assets/voxygen/element/icons/fitness.png (Stored with Git LFS) Normal file

Binary file not shown.

BIN
assets/voxygen/element/icons/willpower.png (Stored with Git LFS) Normal file

Binary file not shown.

View File

@ -150,6 +150,7 @@ impl From<&CharacterAbility> for CharacterState {
stage: 0,
stage_exhausted: false,
stage_time_active: Duration::default(),
should_transition: true,
})
},
}

View File

@ -9,8 +9,9 @@ use vek::vec::Vec2;
// In millis
const STAGE_DURATION: u64 = 600;
const BASE_ACCEL: f32 = 200.0;
const BASE_SPEED: f32 = 250.0;
const INITIAL_ACCEL: f32 = 200.0;
const SECONDARY_ACCEL: f32 = 100.0;
const BASE_SPEED: f32 = 25.0;
/// ### A sequence of 3 incrementally increasing attacks.
///
/// While holding down the `primary` button, perform a series of 3 attacks,
@ -27,6 +28,8 @@ pub struct Data {
pub stage_time_active: Duration,
/// Whether current stage has exhausted its attack
pub stage_exhausted: bool,
/// Whether to go to next stage
pub should_transition: bool,
}
impl CharacterBehavior for Data {
@ -41,42 +44,48 @@ impl CharacterBehavior for Data {
server_events: VecDeque::new(),
};
let new_stage_time_active = self
let stage_time_active = self
.stage_time_active
.checked_add(Duration::from_secs_f32(data.dt.0))
.unwrap_or(Duration::default());
let mut should_transition = self.should_transition;
// If player stops holding input,
if !data.inputs.primary.is_pressed() {
// Done
update.character = CharacterState::Wielding;
// Make sure attack component is removed
data.updater.remove::<Attacking>(data.entity);
return update;
// // Done
// update.character = CharacterState::Wielding;
// // Make sure attack component is removed
// data.updater.remove::<Attacking>(data.entity);
// return update;
should_transition = false;
}
handle_move(data, &mut update);
if self.stage < 3 {
if new_stage_time_active < Duration::from_millis(STAGE_DURATION / 3) {
// Handling movement
if stage_time_active < Duration::from_millis(STAGE_DURATION / 3) {
let adjusted_accel = if self.stage == 0 {
INITIAL_ACCEL
} else {
SECONDARY_ACCEL
};
// Move player forward while in first third of each stage
// Move player according to move_dir
if update.vel.0.magnitude_squared() < BASE_SPEED.powf(2.0) {
update.vel.0 =
update.vel.0 + Vec2::broadcast(data.dt.0) * data.ori.0 * BASE_ACCEL;
update.vel.0 + Vec2::broadcast(data.dt.0) * data.ori.0 * adjusted_accel;
let mag2 = update.vel.0.magnitude_squared();
if mag2 > BASE_SPEED.powf(2.0) {
update.vel.0 = update.vel.0.normalized() * BASE_SPEED;
}
};
} else {
handle_orientation(data, &mut update);
}
update.character = CharacterState::TripleStrike(Data {
base_damage: self.base_damage,
stage: self.stage,
stage_time_active: new_stage_time_active,
stage_exhausted: false,
});
} else if new_stage_time_active > Duration::from_millis(STAGE_DURATION / 2)
// Handling attacking
if stage_time_active > Duration::from_millis(STAGE_DURATION / 2)
&& !self.stage_exhausted
{
// Try to deal damage in second half of stage
@ -90,22 +99,32 @@ impl CharacterBehavior for Data {
update.character = CharacterState::TripleStrike(Data {
base_damage: self.base_damage,
stage: self.stage,
stage_time_active: new_stage_time_active,
stage_time_active,
stage_exhausted: true,
should_transition,
});
} else if new_stage_time_active > Duration::from_millis(STAGE_DURATION) {
update.character = CharacterState::TripleStrike(Data {
base_damage: self.base_damage,
stage: self.stage + 1,
stage_time_active: Duration::default(),
stage_exhausted: false,
});
} else if stage_time_active > Duration::from_millis(STAGE_DURATION) {
if should_transition {
update.character = CharacterState::TripleStrike(Data {
base_damage: self.base_damage,
stage: self.stage + 1,
stage_time_active: Duration::default(),
stage_exhausted: false,
should_transition,
});
} else {
// Done
update.character = CharacterState::Wielding;
// Make sure attack component is removed
data.updater.remove::<Attacking>(data.entity);
}
} else {
update.character = CharacterState::TripleStrike(Data {
base_damage: self.base_damage,
stage: self.stage,
stage_time_active: new_stage_time_active,
stage_time_active,
stage_exhausted: self.stage_exhausted,
should_transition,
});
}
} else {

View File

@ -53,6 +53,10 @@ fn basic_move(data: &JoinData, update: &mut StateUpdate) {
}
}
handle_orientation(data, update);
}
pub fn handle_orientation(data: &JoinData, update: &mut StateUpdate) {
// Set direction based on move direction
let ori_dir = if update.character.is_attack() || update.character.is_block() {
Vec2::from(data.inputs.look_dir).normalized()

View File

@ -1,5 +1,5 @@
use crate::{
comp::{ControlEvent, Controller},
comp::{CharacterState, ControlEvent, Controller},
event::{EventBus, LocalEvent, ServerEvent},
state::DeltaTime,
sync::{Uid, UidAllocator},
@ -22,15 +22,27 @@ impl<'a> System<'a> for Sys {
Read<'a, EventBus<LocalEvent>>,
Read<'a, DeltaTime>,
WriteStorage<'a, Controller>,
WriteStorage<'a, CharacterState>,
ReadStorage<'a, Uid>,
);
fn run(
&mut self,
(entities, uid_allocator, server_bus, _local_bus, _dt, mut controllers, uids): Self::SystemData,
(
entities,
uid_allocator,
server_bus,
_local_bus,
_dt,
mut controllers,
mut character_states,
uids,
): Self::SystemData,
) {
let mut server_emitter = server_bus.emitter();
for (entity, _uid, controller) in (&entities, &uids, &mut controllers).join() {
for (entity, _uid, controller, character_state) in
(&entities, &uids, &mut controllers, &mut character_states).join()
{
let inputs = &mut controller.inputs;
// Update `inputs.move_dir`.
@ -59,6 +71,7 @@ impl<'a> System<'a> for Sys {
},
ControlEvent::Unmount => server_emitter.emit(ServerEvent::Unmount(entity)),
ControlEvent::InventoryManip(manip) => {
*character_state = CharacterState::Idle;
server_emitter.emit(ServerEvent::InventoryManip(entity, manip))
}, /*ControlEvent::Respawn =>
* server_emitter.emit(ServerEvent::Unmount(entity)), */

View File

@ -14,6 +14,7 @@ use conrod_core::{
widget::{self, Button, Image, Rectangle, Text},
widget_ids, Color, Colorable, Labelable, Positionable, Sizeable, Widget, WidgetCommon,
};
//use const_tweaker::tweak;
widget_ids! {
pub struct Ids {
@ -84,6 +85,9 @@ widget_ids! {
tabard_ico,
mainhand_ico,
offhand_ico,
end_ico,
fit_ico,
wp_ico,
}
}
@ -144,10 +148,10 @@ pub enum Event {
Stats,
Close,
}
//#[const_tweaker::tweak(min = -10.0, max = 10.0, step = 1.0)]
//const X: f64 = 10.0;
/*
#[tweak(min = -100.0, max = 20.0, step = 1.0)]
const END_X: f64 = 10.0;
*/
impl<'a> Widget for Bag<'a> {
type Event = Option<Event>;
type State = State;
@ -559,6 +563,21 @@ impl<'a> Widget for Bag<'a> {
.font_size(self.fonts.cyri.scale(16))
.color(TEXT_COLOR)
.set(state.ids.statnames, ui);
Image::new(self.imgs.endurance_ico)
.w_h(30.0, 30.0)
.top_left_with_margins_on(state.ids.statnames, -10.0, -40.0)
.color(Some(UI_HIGHLIGHT_0))
.set(state.ids.end_ico, ui);
Image::new(self.imgs.fitness_ico)
.w_h(30.0, 30.0)
.down_from(state.ids.end_ico, 10.0)
.color(Some(UI_HIGHLIGHT_0))
.set(state.ids.fit_ico, ui);
Image::new(self.imgs.willpower_ico)
.w_h(30.0, 30.0)
.down_from(state.ids.fit_ico, 10.0)
.color(Some(UI_HIGHLIGHT_0))
.set(state.ids.wp_ico, ui);
Text::new(&format!(
"{}\n\n{}\n\n{}",

View File

@ -187,9 +187,6 @@ image_ids! {
divider: "voxygen.element.frames.divider_charwindow",
// Close button
close_button: "voxygen.element.buttons.x",
close_button_hover: "voxygen.element.buttons.x_hover",
close_button_press: "voxygen.element.buttons.x_press",
// Items
@ -227,6 +224,9 @@ image_ids! {
close_btn: "voxygen.element.buttons.close_btn",
close_btn_hover: "voxygen.element.buttons.close_btn_hover",
close_btn_press: "voxygen.element.buttons.close_btn_press",
close_button: "voxygen.element.buttons.close_btn",
close_button_hover: "voxygen.element.buttons.close_btn_hover",
close_button_press: "voxygen.element.buttons.close_btn_press",
// Inventory
coin_ico: "voxygen.element.icons.coin",
@ -258,8 +258,9 @@ image_ids! {
necklace_bg: "voxygen.element.icons.necklace",
mainhand_bg: "voxygen.element.icons.mainhand",
offhand_bg: "voxygen.element.icons.offhand",
willpower_ico: "voxygen.element.icons.willpower",
endurance_ico: "voxygen.element.icons.endurance",
fitness_ico: "voxygen.element.icons.fitness",
not_found:"voxygen.element.not_found",

View File

@ -1,4 +1,4 @@
use super::{img_ids::Imgs, Show, TEXT_COLOR, TEXT_COLOR_3};
use super::{img_ids::Imgs, Show, TEXT_COLOR, TEXT_COLOR_3, UI_MAIN};
use crate::{i18n::VoxygenLocalization, ui::fonts::ConrodVoxygenFonts};
use client::{self, Client};
@ -90,6 +90,7 @@ impl<'a> Widget for Social<'a> {
Image::new(self.imgs.window_3)
.top_left_with_margins_on(ui.window, 200.0, 25.0)
.color(Some(UI_MAIN))
.w_h(103.0 * 4.0, 122.0 * 4.0)
.set(ids.social_frame, ui);
@ -131,6 +132,7 @@ impl<'a> Widget for Social<'a> {
Image::new(self.imgs.social_frame)
.w_h(99.0 * 4.0, 100.0 * 4.0)
.mid_bottom_of(ids.align)
.color(Some(UI_MAIN))
.set(ids.frame, ui);
// Online Tab
@ -156,6 +158,7 @@ impl<'a> Widget for Social<'a> {
.label_font_size(self.fonts.cyri.scale(14))
.label_font_id(self.fonts.cyri.conrod_id)
.parent(ids.frame)
.color(UI_MAIN)
.label_color(TEXT_COLOR)
.set(ids.online_tab, ui)
.was_clicked()
@ -222,6 +225,7 @@ impl<'a> Widget for Social<'a> {
.label_font_size(self.fonts.cyri.scale(14))
.label_font_id(self.fonts.cyri.conrod_id)
.parent(ids.frame)
.color(UI_MAIN)
.label_color(TEXT_COLOR_3)
.set(ids.friends_tab, ui)
.was_clicked()
@ -253,6 +257,7 @@ impl<'a> Widget for Social<'a> {
.parent(ids.frame)
.label_font_size(self.fonts.cyri.scale(14))
.label_font_id(self.fonts.cyri.conrod_id)
.color(UI_MAIN)
.label_color(TEXT_COLOR_3)
.set(ids.faction_tab, ui)
.was_clicked()

View File

@ -1,4 +1,4 @@
use super::{img_ids::Imgs, Show, TEXT_COLOR};
use super::{img_ids::Imgs, Show, TEXT_COLOR, UI_MAIN};
use crate::ui::fonts::ConrodVoxygenFonts;
use conrod_core::{
color,
@ -77,6 +77,7 @@ impl<'a> Widget for Spell<'a> {
Image::new(self.imgs.window_3)
.top_left_with_margins_on(ui.window, 200.0, 25.0)
.w_h(103.0 * 4.0, 122.0 * 4.0)
.color(Some(UI_MAIN))
.set(state.spell_frame, ui);
// X-Button

View File

@ -12,7 +12,7 @@ use crate::{
};
use client::Client;
use common::{
assets::{load_expect, load_glob},
assets::load_expect,
comp::{self, humanoid},
};
use conrod_core::{
@ -22,7 +22,7 @@ use conrod_core::{
widget::{text_box::Event as TextBoxEvent, Button, Image, Rectangle, Scrollbar, Text, TextBox},
widget_ids, Borderable, Color, Colorable, Labelable, Positionable, Sizeable, UiCell, Widget,
};
use std::{borrow::Borrow, sync::Arc};
use std::sync::Arc;
const STARTER_HAMMER: &str = "common.items.weapons.starter_hammer";
const STARTER_BOW: &str = "common.items.weapons.starter_bow";
@ -31,6 +31,10 @@ const STARTER_STAFF: &str = "common.items.weapons.starter_staff";
const STARTER_SWORD: &str = "common.items.weapons.starter_sword";
const STARTER_DAGGER: &str = "common.items.weapons.starter_dagger";
// UI Color-Theme
const UI_MAIN: Color = Color::Rgba(0.61, 0.70, 0.70, 1.0); // Greenish Blue
//const UI_HIGHLIGHT_0: Color = Color::Rgba(0.79, 1.09, 1.09, 1.0);
widget_ids! {
struct Ids {
// Background and logo
@ -383,6 +387,7 @@ impl CharSelectionUi {
Image::new(self.imgs.info_frame)
.w_h(550.0, 150.0)
.middle_of(self.ids.info_bg)
.color(Some(UI_MAIN))
.set(self.ids.info_frame, ui_widgets);
Rectangle::fill_with([275.0, 150.0], color::TRANSPARENT)
.bottom_left_with_margins_on(self.ids.info_frame, 0.0, 0.0)
@ -450,6 +455,7 @@ impl CharSelectionUi {
.set(self.ids.server_frame_bg, ui_widgets);
Image::new(self.imgs.server_frame)
.w_h(400.0, 100.0)
.color(Some(UI_MAIN))
.middle_of(self.ids.server_frame_bg)
.set(self.ids.server_frame, ui_widgets);
@ -460,6 +466,7 @@ impl CharSelectionUi {
Image::new(self.imgs.charlist_frame)
.w_h(400.0, 800.0)
.middle_of(self.ids.charlist_bg)
.color(Some(UI_MAIN))
.set(self.ids.charlist_frame, ui_widgets);
Rectangle::fill_with([386.0, 783.0], color::TRANSPARENT)
.middle_of(self.ids.charlist_bg)
@ -469,7 +476,7 @@ impl CharSelectionUi {
Scrollbar::y_axis(self.ids.charlist_alignment)
.thickness(5.0)
.auto_hide(true)
.rgba(0.0, 0.0, 0., 0.0)
.color(UI_MAIN)
.set(self.ids.selection_scrollbar, ui_widgets);
// Server Name
Text::new(&client.server_info.name)
@ -757,6 +764,7 @@ impl CharSelectionUi {
Image::new(self.imgs.charlist_frame)
.w_h(400.0, ui_widgets.win_h - ui_widgets.win_h * 0.19)
.middle_of(self.ids.creation_bg)
.color(Some(UI_MAIN))
.set(self.ids.charlist_frame, ui_widgets);
Rectangle::fill_with(
[386.0, ui_widgets.win_h - ui_widgets.win_h * 0.19],
@ -864,13 +872,6 @@ impl CharSelectionUi {
"",
&tooltip_human,
)
/*.tooltip_image(
if let humanoid::BodyType::Male = body.body_type {
self.imgs.human_m
} else {
self.imgs.human_f
},
)*/
.set(self.ids.race_1, ui_widgets)
.was_clicked()
{
@ -1029,10 +1030,6 @@ impl CharSelectionUi {
{
*tool = Some(STARTER_HAMMER);
}
// REMOVE THIS AFTER IMPLEMENTATION
/*Rectangle::fill_with([67.0, 67.0], color::rgba(0.0, 0.0, 0.0, 0.8))
.middle_of(self.ids.hammer)
.set(self.ids.hammer_grey, ui_widgets);*/
// Bow
Image::new(self.imgs.bow)
@ -1292,7 +1289,7 @@ impl CharSelectionUi {
.set(self.ids.beard_slider, ui_widgets);
}
// Chest
let armor = load_glob::<comp::Item>("common.items.armor.chest.*")
/*let armor = load_glob::<comp::Item>("common.items.armor.chest.*")
.expect("Unable to load armor!");
if let Some(new_val) = char_slider(
self.ids.beard_slider,
@ -1313,7 +1310,7 @@ impl CharSelectionUi {
ui_widgets,
) {
loadout.chest = Some((*armor[new_val]).clone());
}
}*/
// Pants
/*let current_pants = body.pants;
if let Some(new_val) = char_slider(
@ -1331,7 +1328,7 @@ impl CharSelectionUi {
body.pants = humanoid::ALL_PANTS[new_val];
}*/
Rectangle::fill_with([20.0, 20.0], color::TRANSPARENT)
.down_from(self.ids.chest_slider, 15.0)
.down_from(self.ids.beard_slider, 15.0)
.set(self.ids.space, ui_widgets);
if to_select {

View File

@ -20,6 +20,10 @@ use conrod_core::{
use rand::{seq::SliceRandom, thread_rng};
use std::time::Duration;
// UI Color-Theme
/*const UI_MAIN: Color = Color::Rgba(0.61, 0.70, 0.70, 1.0); // Greenish Blue
const UI_HIGHLIGHT_0: Color = Color::Rgba(0.79, 1.09, 1.09, 1.0);*/
widget_ids! {
struct Ids {
// Background and logo

View File

@ -504,7 +504,14 @@ impl FigureMgr {
)
},
CharacterState::TripleStrike(s) => match s.stage {
0 | 2 => anim::character::AttackAnimation::update_skeleton(
0 => anim::character::AttackAnimation::update_skeleton(
&target_base,
(active_tool_kind, time),
state.state_time,
&mut state_animation_rate,
skeleton_attr,
),
1 => anim::character::AttackAnimation::update_skeleton(
&target_base,
(active_tool_kind, time),
state.state_time,

View File

@ -126,6 +126,8 @@ impl Scene {
/// Set the block position that the player is interacting with
pub fn set_select_pos(&mut self, pos: Option<Vec3<i32>>) { self.select_pos = pos; }
pub fn select_pos(&self) -> Option<Vec3<i32>> { self.select_pos }
/// Handle an incoming user input event (e.g.: cursor moved, key pressed,
/// window closed).
///

View File

@ -269,7 +269,8 @@ impl PlayState for SessionState {
} else {
self.inputs.secondary.set_state(state);
if let Some(select_pos) = select_pos {
// Check for select_block that is highlighted
if let Some(select_pos) = self.scene.select_pos() {
client.collect_block(select_pos);
}
}