mirror of
https://gitlab.com/veloren/veloren.git
synced 2024-08-30 18:12:32 +00:00
Equipped lanterns now provide an illumination effect.
This commit is contained in:
parent
40ab94673e
commit
4e7f8c686a
@ -9,6 +9,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||
|
||||
### Added
|
||||
|
||||
- Player now starts with a lantern. Equipping/unequipping a lantern has the same effect as the `/lantern` command
|
||||
- Added music system
|
||||
- Added zoomable and rotatable minimap
|
||||
- Added rotating orientation marker to main-map
|
||||
|
@ -1,5 +1,12 @@
|
||||
Item(
|
||||
name: "Black Lantern",
|
||||
description: "Used by city guards.",
|
||||
kind: Lantern(Black0),
|
||||
kind: Lantern(
|
||||
(
|
||||
kind: Black0,
|
||||
color: (r: 255, g: 190, b: 75),
|
||||
strength_thousandths: 3000,
|
||||
flicker_thousandths: 300,
|
||||
),
|
||||
),
|
||||
)
|
||||
|
12
assets/common/items/lantern/blue_0.ron
Normal file
12
assets/common/items/lantern/blue_0.ron
Normal file
@ -0,0 +1,12 @@
|
||||
Item(
|
||||
name: "Cool Blue Lantern",
|
||||
description: "This lantern is surprisingly cold when lit.",
|
||||
kind: Lantern(
|
||||
(
|
||||
kind: Blue0,
|
||||
color: (r: 64, g: 127, b: 153),
|
||||
strength_thousandths: 4000,
|
||||
flicker_thousandths: 250,
|
||||
),
|
||||
),
|
||||
)
|
@ -1,5 +1,12 @@
|
||||
Item(
|
||||
name: "Lime Zest Lantern",
|
||||
description: "It has an opening that could fit a ring...",
|
||||
kind: Lantern(Green0),
|
||||
kind: Lantern(
|
||||
(
|
||||
kind: Green0,
|
||||
color: (r: 192, g: 255, b: 76),
|
||||
strength_thousandths: 4000,
|
||||
flicker_thousandths: 500,
|
||||
),
|
||||
),
|
||||
)
|
||||
|
12
assets/common/items/lantern/red_0.ron
Normal file
12
assets/common/items/lantern/red_0.ron
Normal file
@ -0,0 +1,12 @@
|
||||
Item(
|
||||
name: "Red Lantern",
|
||||
description: "Caution: contents hot",
|
||||
kind: Lantern(
|
||||
(
|
||||
kind: Red0,
|
||||
color: (r: 255, g: 127, b: 51),
|
||||
strength_thousandths: 3500,
|
||||
flicker_thousandths: 1000,
|
||||
),
|
||||
),
|
||||
)
|
BIN
assets/voxygen/element/icons/lantern_blue-0.png
(Stored with Git LFS)
Normal file
BIN
assets/voxygen/element/icons/lantern_blue-0.png
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
assets/voxygen/element/icons/lantern_red-0.png
(Stored with Git LFS)
Normal file
BIN
assets/voxygen/element/icons/lantern_red-0.png
(Stored with Git LFS)
Normal file
Binary file not shown.
@ -316,6 +316,7 @@ Enjoy your stay in the World of Veloren."#,
|
||||
"gameinput.climb": "Climb",
|
||||
"gameinput.climbdown": "Climb Down",
|
||||
"gameinput.wallleap": "Wall Leap",
|
||||
"gameinput.togglelantern": "Toggle Lantern",
|
||||
"gameinput.mount": "Mount",
|
||||
"gameinput.enter": "Enter",
|
||||
"gameinput.command": "Command",
|
||||
|
@ -61,6 +61,12 @@
|
||||
Lantern(Green0): Png(
|
||||
"element.icons.lantern_green-0",
|
||||
),
|
||||
Lantern(Blue0): Png(
|
||||
"element.icons.lantern_blue-0",
|
||||
),
|
||||
Lantern(Red0): Png(
|
||||
"element.icons.lantern_red-0",
|
||||
),
|
||||
// Farming Equipment
|
||||
Tool(Farming(Broom)): VoxTrans(
|
||||
"voxel.weapon.tool.broom-0",
|
||||
|
BIN
assets/voxygen/voxel/armor/lantern/blue-0.vox
(Stored with Git LFS)
Normal file
BIN
assets/voxygen/voxel/armor/lantern/blue-0.vox
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
assets/voxygen/voxel/armor/lantern/red-0.vox
(Stored with Git LFS)
Normal file
BIN
assets/voxygen/voxel/armor/lantern/red-0.vox
(Stored with Git LFS)
Normal file
Binary file not shown.
@ -12,5 +12,13 @@
|
||||
vox_spec: ("armor.lantern.black-0", (-2.0, -2.0, -7.0)),
|
||||
color: None
|
||||
),
|
||||
Red0: (
|
||||
vox_spec: ("armor.lantern.red-0", (-2.0, -2.0, -7.0)),
|
||||
color: None
|
||||
),
|
||||
Blue0: (
|
||||
vox_spec: ("armor.lantern.blue-0", (-2.0, -2.0, -7.0)),
|
||||
color: None
|
||||
),
|
||||
},
|
||||
))
|
||||
|
@ -274,6 +274,11 @@ impl Client {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn toggle_lantern(&mut self) {
|
||||
self.postbox
|
||||
.send_message(ClientMsg::ControlEvent(ControlEvent::ToggleLantern));
|
||||
}
|
||||
|
||||
pub fn is_mounted(&self) -> bool {
|
||||
self.state
|
||||
.ecs()
|
||||
|
@ -167,7 +167,7 @@ pub fn load_cloned<A: Asset + Clone + 'static>(specifier: &str) -> Result<A, Err
|
||||
pub fn load_expect<A: Asset + 'static>(specifier: &str) -> Arc<A> {
|
||||
load(specifier).unwrap_or_else(|err| {
|
||||
panic!(
|
||||
"Failed loading essential asset: {} (error={})",
|
||||
"Failed loading essential asset: {} (error={:?})",
|
||||
specifier, err
|
||||
)
|
||||
})
|
||||
|
@ -18,6 +18,7 @@ pub enum InventoryManip {
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
|
||||
pub enum ControlEvent {
|
||||
ToggleLantern,
|
||||
Mount(Uid),
|
||||
Unmount,
|
||||
InventoryManip(InventoryManip),
|
||||
|
@ -13,6 +13,7 @@ use rand::seq::SliceRandom;
|
||||
use specs::{Component, FlaggedStorage};
|
||||
use specs_idvs::IDVStorage;
|
||||
use std::{fs::File, io::BufReader};
|
||||
use vek::Rgb;
|
||||
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
|
||||
pub enum Consumable {
|
||||
@ -39,11 +40,33 @@ pub enum Ingredient {
|
||||
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
|
||||
#[repr(u32)]
|
||||
pub enum Lantern {
|
||||
pub enum LanternKind {
|
||||
Black0 = 1,
|
||||
Green0 = 2,
|
||||
Red0 = 3,
|
||||
Blue0 = 4,
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
|
||||
pub struct Lantern {
|
||||
pub kind: LanternKind,
|
||||
color: Rgb<u32>,
|
||||
strength_thousandths: u32,
|
||||
flicker_thousandths: u32,
|
||||
}
|
||||
|
||||
pub const ALL_LANTERNS: [LanternKind; 4] = [
|
||||
LanternKind::Black0,
|
||||
LanternKind::Green0,
|
||||
LanternKind::Red0,
|
||||
LanternKind::Blue0,
|
||||
];
|
||||
|
||||
impl Lantern {
|
||||
pub fn strength(&self) -> f32 { self.strength_thousandths as f32 / 1000_f32 }
|
||||
|
||||
pub fn color(&self) -> Rgb<f32> { self.color.map(|c| c as f32 / 255.0) }
|
||||
}
|
||||
pub const ALL_LANTERNS: [Lantern; 2] = [Lantern::Black0, Lantern::Green0];
|
||||
|
||||
fn default_amount() -> u32 { 1 }
|
||||
|
||||
|
@ -3,6 +3,7 @@ pub mod slot;
|
||||
|
||||
use crate::assets;
|
||||
use item::{Consumable, Item, ItemKind};
|
||||
use rand::{seq::SliceRandom, thread_rng};
|
||||
use specs::{Component, FlaggedStorage, HashMapStorage};
|
||||
use specs_idvs::IDVStorage;
|
||||
use std::ops::Not;
|
||||
@ -304,6 +305,15 @@ impl Default for Inventory {
|
||||
};
|
||||
inventory.push(assets::load_expect_cloned("common.items.cheese"));
|
||||
inventory.push(assets::load_expect_cloned("common.items.apple"));
|
||||
let mut rng = thread_rng();
|
||||
let starter_lantern = [
|
||||
"common.items.lantern.black_0",
|
||||
"common.items.lantern.red_0",
|
||||
"common.items.lantern.blue_0",
|
||||
]
|
||||
.choose(&mut rng)
|
||||
.unwrap();
|
||||
inventory.push(assets::load_expect_cloned(starter_lantern));
|
||||
inventory
|
||||
}
|
||||
}
|
||||
|
@ -6,9 +6,9 @@ lazy_static! {
|
||||
assets::load_expect_cloned("common.items.debug.possess")
|
||||
];
|
||||
}
|
||||
/// The `Default` inventory should contain two items
|
||||
/// The `Default` inventory should contain 3 items: cheese, apple, lantern
|
||||
#[test]
|
||||
fn create_default_count() { assert_eq!(Inventory::default().count(), 2) }
|
||||
fn create_default_count() { assert_eq!(Inventory::default().count(), 3) }
|
||||
|
||||
/// Attempting to push into a full inventory should return the same item.
|
||||
#[test]
|
||||
|
@ -39,4 +39,4 @@ pub use phys::{Collider, ForceUpdate, Gravity, Mass, Ori, PhysicsState, Pos, Sca
|
||||
pub use player::Player;
|
||||
pub use projectile::Projectile;
|
||||
pub use stats::{Exp, HealthChange, HealthSource, Level, Stats};
|
||||
pub use visual::LightEmitter;
|
||||
pub use visual::{LightAnimation, LightEmitter};
|
||||
|
@ -4,17 +4,19 @@ use vek::*;
|
||||
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Serialize, Deserialize)]
|
||||
pub struct LightEmitter {
|
||||
pub offset: Vec3<f32>,
|
||||
pub col: Rgb<f32>,
|
||||
pub strength: f32,
|
||||
pub flicker: f32,
|
||||
pub animated: bool,
|
||||
}
|
||||
|
||||
impl Default for LightEmitter {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
offset: Vec3::zero(),
|
||||
col: Rgb::one(),
|
||||
strength: 1.0,
|
||||
flicker: 0.0,
|
||||
animated: false,
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -22,3 +24,24 @@ impl Default for LightEmitter {
|
||||
impl Component for LightEmitter {
|
||||
type Storage = FlaggedStorage<Self, IDVStorage<Self>>;
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Serialize, Deserialize)]
|
||||
pub struct LightAnimation {
|
||||
pub offset: Vec3<f32>,
|
||||
pub col: Rgb<f32>,
|
||||
pub strength: f32,
|
||||
}
|
||||
|
||||
impl Default for LightAnimation {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
offset: Vec3::zero(),
|
||||
col: Rgb::zero(),
|
||||
strength: 0.0,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Component for LightAnimation {
|
||||
type Storage = FlaggedStorage<Self, IDVStorage<Self>>;
|
||||
}
|
||||
|
@ -86,6 +86,7 @@ pub enum ServerEvent {
|
||||
entity: EcsEntity,
|
||||
vel: Vec3<f32>,
|
||||
},
|
||||
ToggleLantern(EcsEntity),
|
||||
Mount(EcsEntity, EcsEntity),
|
||||
Unmount(EcsEntity),
|
||||
Possess(Uid, Uid),
|
||||
|
@ -135,6 +135,10 @@ impl State {
|
||||
ecs.register::<comp::Ori>();
|
||||
ecs.register::<comp::Inventory>();
|
||||
|
||||
// Register client-local components
|
||||
// TODO: only register on the client
|
||||
ecs.register::<comp::LightAnimation>();
|
||||
|
||||
// Register server-local components
|
||||
// TODO: only register on the server
|
||||
ecs.register::<comp::Last<comp::Pos>>();
|
||||
|
@ -74,6 +74,9 @@ impl<'a> System<'a> for Sys {
|
||||
}
|
||||
},
|
||||
ControlEvent::Unmount => server_emitter.emit(ServerEvent::Unmount(entity)),
|
||||
ControlEvent::ToggleLantern => {
|
||||
server_emitter.emit(ServerEvent::ToggleLantern(entity))
|
||||
},
|
||||
ControlEvent::InventoryManip(manip) => {
|
||||
*character_state = CharacterState::Idle;
|
||||
server_emitter.emit(ServerEvent::InventoryManip(entity, manip))
|
||||
|
@ -202,9 +202,9 @@ lazy_static! {
|
||||
),
|
||||
ChatCommand::new(
|
||||
"lantern",
|
||||
"{}",
|
||||
"/lantern : adds/remove light near player",
|
||||
false,
|
||||
"{} {} {} {}",
|
||||
"/lantern <strength> [<r> <g> <b>]: Change your lantern's strength and color",
|
||||
true,
|
||||
handle_lantern,
|
||||
),
|
||||
ChatCommand::new(
|
||||
@ -847,6 +847,7 @@ fn handle_light(
|
||||
scan_fmt_some!(&args, action.arg_fmt, f32, f32, f32, f32, f32, f32, f32);
|
||||
|
||||
let mut light_emitter = comp::LightEmitter::default();
|
||||
let mut light_offset_opt = None;
|
||||
|
||||
if let (Some(r), Some(g), Some(b)) = (opt_r, opt_g, opt_b) {
|
||||
let r = r.max(0.0).min(1.0);
|
||||
@ -855,7 +856,11 @@ fn handle_light(
|
||||
light_emitter.col = Rgb::new(r, g, b)
|
||||
};
|
||||
if let (Some(x), Some(y), Some(z)) = (opt_x, opt_y, opt_z) {
|
||||
light_emitter.offset = Vec3::new(x, y, z)
|
||||
light_offset_opt = Some(comp::LightAnimation {
|
||||
offset: Vec3::new(x, y, z),
|
||||
col: light_emitter.col,
|
||||
strength: 0.0,
|
||||
})
|
||||
};
|
||||
if let Some(s) = opt_s {
|
||||
light_emitter.strength = s.max(0.0)
|
||||
@ -867,14 +872,18 @@ fn handle_light(
|
||||
.get(target)
|
||||
.copied();
|
||||
if let Some(pos) = pos {
|
||||
server
|
||||
let builder = server
|
||||
.state
|
||||
.ecs_mut()
|
||||
.create_entity_synced()
|
||||
.with(pos)
|
||||
.with(comp::ForceUpdate)
|
||||
.with(light_emitter)
|
||||
.build();
|
||||
.with(light_emitter);
|
||||
if let Some(light_offset) = light_offset_opt {
|
||||
builder.with(light_offset).build();
|
||||
} else {
|
||||
builder.build();
|
||||
}
|
||||
server.notify_client(client, ServerMsg::private(format!("Spawned object.")));
|
||||
} else {
|
||||
server.notify_client(client, ServerMsg::private(format!("You have no position!")));
|
||||
@ -888,15 +897,7 @@ fn handle_lantern(
|
||||
args: String,
|
||||
action: &ChatCommand,
|
||||
) {
|
||||
let opt_s = scan_fmt_some!(&args, action.arg_fmt, f32);
|
||||
|
||||
if server
|
||||
.state
|
||||
.read_storage::<comp::LightEmitter>()
|
||||
.get(target)
|
||||
.is_some()
|
||||
{
|
||||
if let Some(s) = opt_s {
|
||||
if let (Some(s), r, g, b) = scan_fmt_some!(&args, action.arg_fmt, f32, f32, f32, f32) {
|
||||
if let Some(light) = server
|
||||
.state
|
||||
.ecs()
|
||||
@ -904,41 +905,31 @@ fn handle_lantern(
|
||||
.get_mut(target)
|
||||
{
|
||||
light.strength = s.max(0.1).min(10.0);
|
||||
if let (Some(r), Some(g), Some(b)) = (r, g, b) {
|
||||
light.col = (
|
||||
r.max(0.0).min(1.0),
|
||||
g.max(0.0).min(1.0),
|
||||
b.max(0.0).min(1.0),
|
||||
)
|
||||
.into();
|
||||
server.notify_client(
|
||||
client,
|
||||
ServerMsg::private(String::from("You adjusted flame strength and color.")),
|
||||
);
|
||||
} else {
|
||||
server.notify_client(
|
||||
client,
|
||||
ServerMsg::private(String::from("You adjusted flame strength.")),
|
||||
);
|
||||
}
|
||||
} else {
|
||||
server
|
||||
.state
|
||||
.ecs()
|
||||
.write_storage::<comp::LightEmitter>()
|
||||
.remove(target);
|
||||
server.notify_client(
|
||||
client,
|
||||
ServerMsg::private(String::from("You put out the lantern.")),
|
||||
ServerMsg::private(String::from("Please equip a lantern first")),
|
||||
);
|
||||
}
|
||||
} else {
|
||||
let _ = server
|
||||
.state
|
||||
.ecs()
|
||||
.write_storage::<comp::LightEmitter>()
|
||||
.insert(target, comp::LightEmitter {
|
||||
offset: Vec3::new(0.5, 0.2, 0.8),
|
||||
col: Rgb::new(1.0, 0.75, 0.3),
|
||||
strength: if let Some(s) = opt_s {
|
||||
s.max(0.0).min(10.0)
|
||||
} else {
|
||||
3.0
|
||||
},
|
||||
});
|
||||
|
||||
server.notify_client(
|
||||
client,
|
||||
ServerMsg::private(String::from("You lit your lantern.")),
|
||||
);
|
||||
server.notify_client(client, ServerMsg::private(String::from(action.help_string)));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -79,9 +79,10 @@ pub fn handle_create_waypoint(server: &mut Server, pos: Vec3<f32>) {
|
||||
.state
|
||||
.create_object(Pos(pos), comp::object::Body::CampfireLit)
|
||||
.with(LightEmitter {
|
||||
offset: Vec3::unit_z() * 0.5,
|
||||
col: Rgb::new(1.0, 0.65, 0.2),
|
||||
strength: 2.0,
|
||||
flicker: 1.0,
|
||||
animated: true,
|
||||
})
|
||||
.with(WaypointArea::default())
|
||||
.build();
|
||||
|
@ -86,6 +86,10 @@ pub fn handle_destroy(server: &mut Server, entity: EcsEntity, cause: HealthSourc
|
||||
.insert(entity, comp::ForceUpdate)
|
||||
.err()
|
||||
.map(|err| error!("Failed to insert ForceUpdate on dead client: {:?}", err));
|
||||
state
|
||||
.ecs()
|
||||
.write_storage::<comp::LightEmitter>()
|
||||
.remove(entity);
|
||||
state
|
||||
.ecs()
|
||||
.write_storage::<comp::Energy>()
|
||||
|
@ -11,6 +11,43 @@ use common::{
|
||||
use log::error;
|
||||
use specs::{world::WorldExt, Entity as EcsEntity};
|
||||
|
||||
pub fn handle_lantern(server: &mut Server, entity: EcsEntity) {
|
||||
let ecs = server.state_mut().ecs();
|
||||
if ecs
|
||||
.read_storage::<comp::LightEmitter>()
|
||||
.get(entity)
|
||||
.map_or(false, |light| light.strength > 0.0)
|
||||
{
|
||||
server
|
||||
.state_mut()
|
||||
.ecs()
|
||||
.write_storage::<comp::LightEmitter>()
|
||||
.remove(entity);
|
||||
} else {
|
||||
let lantern_opt = ecs
|
||||
.read_storage::<comp::Loadout>()
|
||||
.get(entity)
|
||||
.and_then(|loadout| loadout.lantern.as_ref())
|
||||
.and_then(|item| {
|
||||
if let comp::item::ItemKind::Lantern(l) = item.kind {
|
||||
Some(l)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
});
|
||||
if let Some(lantern) = lantern_opt {
|
||||
let _ = ecs
|
||||
.write_storage::<comp::LightEmitter>()
|
||||
.insert(entity, comp::LightEmitter {
|
||||
col: lantern.color(),
|
||||
strength: lantern.strength(),
|
||||
flicker: 1.0,
|
||||
animated: true,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn handle_mount(server: &mut Server, mounter: EcsEntity, mountee: EcsEntity) {
|
||||
let state = server.state_mut();
|
||||
|
||||
|
@ -11,9 +11,24 @@ use common::{
|
||||
};
|
||||
use log::error;
|
||||
use rand::Rng;
|
||||
use specs::{join::Join, world::WorldExt, Builder, Entity as EcsEntity};
|
||||
use specs::{join::Join, world::WorldExt, Builder, Entity as EcsEntity, WriteStorage};
|
||||
use vek::Vec3;
|
||||
|
||||
pub fn swap_lantern(
|
||||
storage: &mut WriteStorage<comp::LightEmitter>,
|
||||
entity: EcsEntity,
|
||||
lantern: &item::Lantern,
|
||||
) {
|
||||
if let Some(light) = storage.get_mut(entity) {
|
||||
light.strength = lantern.strength();
|
||||
light.col = lantern.color();
|
||||
}
|
||||
}
|
||||
|
||||
pub fn snuff_lantern(storage: &mut WriteStorage<comp::LightEmitter>, entity: EcsEntity) {
|
||||
storage.remove(entity);
|
||||
}
|
||||
|
||||
pub fn handle_inventory(server: &mut Server, entity: EcsEntity, manip: comp::InventoryManip) {
|
||||
let state = server.state_mut();
|
||||
let mut dropped_items = Vec::new();
|
||||
@ -101,12 +116,19 @@ pub fn handle_inventory(server: &mut Server, entity: EcsEntity, manip: comp::Inv
|
||||
let event = match slot {
|
||||
Slot::Inventory(slot) => {
|
||||
use item::ItemKind;
|
||||
// Check if item is equipable
|
||||
if inventory.get(slot).map_or(false, |i| match &i.kind {
|
||||
ItemKind::Tool(_) | ItemKind::Armor { .. } | ItemKind::Lantern(_) => true,
|
||||
_ => false,
|
||||
}) {
|
||||
let (is_equippable, lantern_opt) =
|
||||
inventory
|
||||
.get(slot)
|
||||
.map_or((false, None), |i| match &i.kind {
|
||||
ItemKind::Tool(_) | ItemKind::Armor { .. } => (true, None),
|
||||
ItemKind::Lantern(lantern) => (true, Some(lantern)),
|
||||
_ => (false, None),
|
||||
});
|
||||
if is_equippable {
|
||||
if let Some(loadout) = state.ecs().write_storage().get_mut(entity) {
|
||||
if let Some(lantern) = lantern_opt {
|
||||
swap_lantern(&mut state.ecs().write_storage(), entity, lantern);
|
||||
}
|
||||
slot::equip(slot, inventory, loadout);
|
||||
Some(comp::InventoryUpdateEvent::Used)
|
||||
} else {
|
||||
@ -191,6 +213,9 @@ pub fn handle_inventory(server: &mut Server, entity: EcsEntity, manip: comp::Inv
|
||||
},
|
||||
Slot::Equip(slot) => {
|
||||
if let Some(loadout) = state.ecs().write_storage().get_mut(entity) {
|
||||
if slot == slot::EquipSlot::Lantern {
|
||||
snuff_lantern(&mut state.ecs().write_storage(), entity);
|
||||
}
|
||||
slot::unequip(slot, inventory, loadout);
|
||||
Some(comp::InventoryUpdateEvent::Used)
|
||||
} else {
|
||||
|
@ -6,7 +6,7 @@ use entity_creation::{
|
||||
use entity_manipulation::{
|
||||
handle_damage, handle_destroy, handle_explosion, handle_land_on_ground, handle_respawn,
|
||||
};
|
||||
use interaction::{handle_mount, handle_possess, handle_unmount};
|
||||
use interaction::{handle_lantern, handle_mount, handle_possess, handle_unmount};
|
||||
use inventory_manip::handle_inventory;
|
||||
use player::{handle_client_disconnect, handle_exit_ingame};
|
||||
use specs::{Entity as EcsEntity, WorldExt};
|
||||
@ -63,6 +63,7 @@ impl Server {
|
||||
ServerEvent::LandOnGround { entity, vel } => {
|
||||
handle_land_on_ground(&self, entity, vel)
|
||||
},
|
||||
ServerEvent::ToggleLantern(entity) => handle_lantern(self, entity),
|
||||
ServerEvent::Mount(mounter, mountee) => handle_mount(self, mounter, mountee),
|
||||
ServerEvent::Unmount(mounter) => handle_unmount(self, mounter),
|
||||
ServerEvent::Possess(possessor_uid, possesse_uid) => {
|
||||
|
@ -127,7 +127,6 @@ impl StateExt for State {
|
||||
z_max: 0.9,
|
||||
})
|
||||
.with(comp::Gravity(1.0))
|
||||
//.with(comp::LightEmitter::default())
|
||||
}
|
||||
|
||||
/// Build a projectile
|
||||
|
@ -8,6 +8,7 @@ pub use self::{idle::IdleAnimation, jump::JumpAnimation, run::RunAnimation};
|
||||
use super::{Bone, Skeleton};
|
||||
use crate::render::FigureBoneData;
|
||||
use common::comp::{self};
|
||||
use vek::Vec3;
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct BipedLargeSkeleton {
|
||||
@ -49,7 +50,7 @@ impl Skeleton for BipedLargeSkeleton {
|
||||
|
||||
fn bone_count(&self) -> usize { 11 }
|
||||
|
||||
fn compute_matrices(&self) -> [FigureBoneData; 16] {
|
||||
fn compute_matrices(&self) -> ([FigureBoneData; 16], Vec3<f32>) {
|
||||
let upper_torso_mat = self.upper_torso.compute_base_matrix();
|
||||
let shoulder_l_mat = self.shoulder_l.compute_base_matrix();
|
||||
let shoulder_r_mat = self.shoulder_r.compute_base_matrix();
|
||||
@ -57,6 +58,7 @@ impl Skeleton for BipedLargeSkeleton {
|
||||
let leg_r_mat = self.leg_r.compute_base_matrix();
|
||||
let torso_mat = self.torso.compute_base_matrix();
|
||||
|
||||
(
|
||||
[
|
||||
FigureBoneData::new(torso_mat * upper_torso_mat * self.head.compute_base_matrix()),
|
||||
FigureBoneData::new(torso_mat * upper_torso_mat),
|
||||
@ -65,8 +67,12 @@ impl Skeleton for BipedLargeSkeleton {
|
||||
),
|
||||
FigureBoneData::new(torso_mat * upper_torso_mat * shoulder_l_mat),
|
||||
FigureBoneData::new(torso_mat * upper_torso_mat * shoulder_r_mat),
|
||||
FigureBoneData::new(torso_mat * upper_torso_mat * self.hand_l.compute_base_matrix()),
|
||||
FigureBoneData::new(torso_mat * upper_torso_mat * self.hand_r.compute_base_matrix()),
|
||||
FigureBoneData::new(
|
||||
torso_mat * upper_torso_mat * self.hand_l.compute_base_matrix(),
|
||||
),
|
||||
FigureBoneData::new(
|
||||
torso_mat * upper_torso_mat * self.hand_r.compute_base_matrix(),
|
||||
),
|
||||
FigureBoneData::new(torso_mat * upper_torso_mat * leg_l_mat),
|
||||
FigureBoneData::new(torso_mat * upper_torso_mat * leg_r_mat),
|
||||
FigureBoneData::new(self.foot_l.compute_base_matrix()),
|
||||
@ -76,7 +82,9 @@ impl Skeleton for BipedLargeSkeleton {
|
||||
FigureBoneData::default(),
|
||||
FigureBoneData::default(),
|
||||
FigureBoneData::default(),
|
||||
]
|
||||
],
|
||||
Vec3::default(),
|
||||
)
|
||||
}
|
||||
|
||||
fn interpolate(&mut self, target: &Self, dt: f32) {
|
||||
|
@ -8,6 +8,7 @@ pub use self::{fly::FlyAnimation, idle::IdleAnimation, run::RunAnimation};
|
||||
use super::{Bone, Skeleton};
|
||||
use crate::render::FigureBoneData;
|
||||
use common::comp::{self};
|
||||
use vek::Vec3;
|
||||
|
||||
#[derive(Clone, Default)]
|
||||
pub struct BirdMediumSkeleton {
|
||||
@ -29,9 +30,10 @@ impl Skeleton for BirdMediumSkeleton {
|
||||
|
||||
fn bone_count(&self) -> usize { 7 }
|
||||
|
||||
fn compute_matrices(&self) -> [FigureBoneData; 16] {
|
||||
fn compute_matrices(&self) -> ([FigureBoneData; 16], Vec3<f32>) {
|
||||
let torso_mat = self.torso.compute_base_matrix();
|
||||
|
||||
(
|
||||
[
|
||||
FigureBoneData::new(torso_mat * self.head.compute_base_matrix()),
|
||||
FigureBoneData::new(torso_mat),
|
||||
@ -49,7 +51,9 @@ impl Skeleton for BirdMediumSkeleton {
|
||||
FigureBoneData::default(),
|
||||
FigureBoneData::default(),
|
||||
FigureBoneData::default(),
|
||||
]
|
||||
],
|
||||
Vec3::default(),
|
||||
)
|
||||
}
|
||||
|
||||
fn interpolate(&mut self, target: &Self, dt: f32) {
|
||||
|
@ -8,6 +8,7 @@ pub use self::{idle::IdleAnimation, jump::JumpAnimation, run::RunAnimation};
|
||||
use super::{Bone, Skeleton};
|
||||
use crate::render::FigureBoneData;
|
||||
use common::comp::{self};
|
||||
use vek::Vec3;
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct BirdSmallSkeleton {
|
||||
@ -33,9 +34,10 @@ impl Skeleton for BirdSmallSkeleton {
|
||||
|
||||
fn bone_count(&self) -> usize { 4 }
|
||||
|
||||
fn compute_matrices(&self) -> [FigureBoneData; 16] {
|
||||
fn compute_matrices(&self) -> ([FigureBoneData; 16], Vec3<f32>) {
|
||||
let torso_mat = self.torso.compute_base_matrix();
|
||||
|
||||
(
|
||||
[
|
||||
FigureBoneData::new(self.head.compute_base_matrix() * torso_mat),
|
||||
FigureBoneData::new(torso_mat),
|
||||
@ -53,7 +55,9 @@ impl Skeleton for BirdSmallSkeleton {
|
||||
FigureBoneData::default(),
|
||||
FigureBoneData::default(),
|
||||
FigureBoneData::default(),
|
||||
]
|
||||
],
|
||||
Vec3::default(),
|
||||
)
|
||||
}
|
||||
|
||||
fn interpolate(&mut self, target: &Self, dt: f32) {
|
||||
|
@ -31,6 +31,7 @@ pub use self::{
|
||||
use super::{Bone, Skeleton};
|
||||
use crate::render::FigureBoneData;
|
||||
use common::comp;
|
||||
use vek::{Vec3, Vec4};
|
||||
|
||||
#[derive(Clone, Default)]
|
||||
pub struct CharacterSkeleton {
|
||||
@ -64,7 +65,7 @@ impl Skeleton for CharacterSkeleton {
|
||||
|
||||
fn bone_count(&self) -> usize { 15 }
|
||||
|
||||
fn compute_matrices(&self) -> [FigureBoneData; 16] {
|
||||
fn compute_matrices(&self) -> ([FigureBoneData; 16], Vec3<f32>) {
|
||||
let chest_mat = self.chest.compute_base_matrix();
|
||||
let torso_mat = self.torso.compute_base_matrix();
|
||||
let l_hand_mat = self.l_hand.compute_base_matrix();
|
||||
@ -76,26 +77,37 @@ impl Skeleton for CharacterSkeleton {
|
||||
let second_mat = self.second.compute_base_matrix();
|
||||
let shorts_mat = self.shorts.compute_base_matrix();
|
||||
let head_mat = self.head.compute_base_matrix();
|
||||
|
||||
let lantern_final_mat =
|
||||
torso_mat * chest_mat * shorts_mat * self.lantern.compute_base_matrix();
|
||||
|
||||
(
|
||||
[
|
||||
FigureBoneData::new(torso_mat * chest_mat * head_mat),
|
||||
FigureBoneData::new(torso_mat * chest_mat),
|
||||
FigureBoneData::new(torso_mat * chest_mat * self.belt.compute_base_matrix()),
|
||||
FigureBoneData::new(torso_mat * chest_mat * self.back.compute_base_matrix()),
|
||||
FigureBoneData::new(torso_mat * chest_mat * shorts_mat),
|
||||
FigureBoneData::new(torso_mat * chest_mat * control_mat * l_control_mat * l_hand_mat),
|
||||
FigureBoneData::new(torso_mat * chest_mat * control_mat * r_control_mat * r_hand_mat),
|
||||
FigureBoneData::new(
|
||||
torso_mat * chest_mat * control_mat * l_control_mat * l_hand_mat,
|
||||
),
|
||||
FigureBoneData::new(
|
||||
torso_mat * chest_mat * control_mat * r_control_mat * r_hand_mat,
|
||||
),
|
||||
FigureBoneData::new(torso_mat * self.l_foot.compute_base_matrix()),
|
||||
FigureBoneData::new(torso_mat * self.r_foot.compute_base_matrix()),
|
||||
FigureBoneData::new(torso_mat * chest_mat * self.l_shoulder.compute_base_matrix()),
|
||||
FigureBoneData::new(torso_mat * chest_mat * self.r_shoulder.compute_base_matrix()),
|
||||
FigureBoneData::new(torso_mat * self.glider.compute_base_matrix()),
|
||||
FigureBoneData::new(torso_mat * chest_mat * control_mat * l_control_mat * main_mat),
|
||||
FigureBoneData::new(torso_mat * chest_mat * control_mat * r_control_mat * second_mat),
|
||||
FigureBoneData::new(
|
||||
torso_mat * chest_mat * shorts_mat * self.lantern.compute_base_matrix(),
|
||||
torso_mat * chest_mat * control_mat * r_control_mat * second_mat,
|
||||
),
|
||||
FigureBoneData::new(lantern_final_mat),
|
||||
FigureBoneData::default(),
|
||||
]
|
||||
],
|
||||
(lantern_final_mat * Vec4::new(0.0, 0.0, 0.0, 1.0)).xyz(),
|
||||
)
|
||||
}
|
||||
|
||||
fn interpolate(&mut self, target: &Self, dt: f32) {
|
||||
|
@ -8,6 +8,7 @@ pub use self::{idle::IdleAnimation, jump::JumpAnimation, run::RunAnimation};
|
||||
use super::{Bone, Skeleton};
|
||||
use crate::render::FigureBoneData;
|
||||
use common::comp::{self};
|
||||
use vek::Vec3;
|
||||
|
||||
#[derive(Clone, Default)]
|
||||
pub struct CritterSkeleton {
|
||||
@ -34,7 +35,8 @@ impl Skeleton for CritterSkeleton {
|
||||
|
||||
fn bone_count(&self) -> usize { 5 }
|
||||
|
||||
fn compute_matrices(&self) -> [FigureBoneData; 16] {
|
||||
fn compute_matrices(&self) -> ([FigureBoneData; 16], Vec3<f32>) {
|
||||
(
|
||||
[
|
||||
FigureBoneData::new(self.head.compute_base_matrix()),
|
||||
FigureBoneData::new(self.chest.compute_base_matrix()),
|
||||
@ -52,7 +54,9 @@ impl Skeleton for CritterSkeleton {
|
||||
FigureBoneData::default(),
|
||||
FigureBoneData::default(),
|
||||
FigureBoneData::default(),
|
||||
]
|
||||
],
|
||||
Vec3::default(),
|
||||
)
|
||||
}
|
||||
|
||||
fn interpolate(&mut self, target: &Self, dt: f32) {
|
||||
|
@ -8,6 +8,7 @@ pub use self::{idle::IdleAnimation, jump::JumpAnimation, run::RunAnimation};
|
||||
use super::{Bone, Skeleton};
|
||||
use crate::render::FigureBoneData;
|
||||
use common::comp::{self};
|
||||
use vek::Vec3;
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct DragonSkeleton {
|
||||
@ -51,12 +52,13 @@ impl Skeleton for DragonSkeleton {
|
||||
|
||||
fn bone_count(&self) -> usize { 13 }
|
||||
|
||||
fn compute_matrices(&self) -> [FigureBoneData; 16] {
|
||||
fn compute_matrices(&self) -> ([FigureBoneData; 16], Vec3<f32>) {
|
||||
let chest_front_mat = self.chest_front.compute_base_matrix();
|
||||
let wing_in_l_mat = self.wing_in_l.compute_base_matrix();
|
||||
let wing_in_r_mat = self.wing_in_r.compute_base_matrix();
|
||||
let tail_front_mat = self.tail_front.compute_base_matrix();
|
||||
|
||||
(
|
||||
[
|
||||
FigureBoneData::new(self.head.compute_base_matrix() * chest_front_mat),
|
||||
FigureBoneData::new(chest_front_mat),
|
||||
@ -74,7 +76,9 @@ impl Skeleton for DragonSkeleton {
|
||||
FigureBoneData::default(),
|
||||
FigureBoneData::default(),
|
||||
FigureBoneData::default(),
|
||||
]
|
||||
],
|
||||
Vec3::default(),
|
||||
)
|
||||
}
|
||||
|
||||
fn interpolate(&mut self, target: &Self, dt: f32) {
|
||||
|
@ -8,6 +8,7 @@ pub use self::{idle::IdleAnimation, jump::JumpAnimation, run::RunAnimation};
|
||||
use super::{Bone, Skeleton};
|
||||
use crate::render::FigureBoneData;
|
||||
use common::comp::{self};
|
||||
use vek::Vec3;
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct FishMediumSkeleton {
|
||||
@ -37,10 +38,11 @@ impl Skeleton for FishMediumSkeleton {
|
||||
|
||||
fn bone_count(&self) -> usize { 6 }
|
||||
|
||||
fn compute_matrices(&self) -> [FigureBoneData; 16] {
|
||||
fn compute_matrices(&self) -> ([FigureBoneData; 16], Vec3<f32>) {
|
||||
let torso_mat = self.torso.compute_base_matrix();
|
||||
let rear_mat = self.rear.compute_base_matrix();
|
||||
|
||||
(
|
||||
[
|
||||
FigureBoneData::new(self.head.compute_base_matrix() * torso_mat),
|
||||
FigureBoneData::new(torso_mat),
|
||||
@ -58,7 +60,9 @@ impl Skeleton for FishMediumSkeleton {
|
||||
FigureBoneData::default(),
|
||||
FigureBoneData::default(),
|
||||
FigureBoneData::default(),
|
||||
]
|
||||
],
|
||||
Vec3::default(),
|
||||
)
|
||||
}
|
||||
|
||||
fn interpolate(&mut self, target: &Self, dt: f32) {
|
||||
|
@ -8,6 +8,7 @@ pub use self::{idle::IdleAnimation, jump::JumpAnimation, run::RunAnimation};
|
||||
use super::{Bone, Skeleton};
|
||||
use crate::render::FigureBoneData;
|
||||
use common::comp::{self};
|
||||
use vek::Vec3;
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct FishSmallSkeleton {
|
||||
@ -29,9 +30,10 @@ impl Skeleton for FishSmallSkeleton {
|
||||
|
||||
fn bone_count(&self) -> usize { 2 }
|
||||
|
||||
fn compute_matrices(&self) -> [FigureBoneData; 16] {
|
||||
fn compute_matrices(&self) -> ([FigureBoneData; 16], Vec3<f32>) {
|
||||
let torso_mat = self.torso.compute_base_matrix();
|
||||
|
||||
(
|
||||
[
|
||||
FigureBoneData::new(torso_mat),
|
||||
FigureBoneData::new(self.tail.compute_base_matrix() * torso_mat),
|
||||
@ -49,7 +51,9 @@ impl Skeleton for FishSmallSkeleton {
|
||||
FigureBoneData::default(),
|
||||
FigureBoneData::default(),
|
||||
FigureBoneData::default(),
|
||||
]
|
||||
],
|
||||
Vec3::default(),
|
||||
)
|
||||
}
|
||||
|
||||
fn interpolate(&mut self, target: &Self, dt: f32) {
|
||||
|
@ -1,5 +1,6 @@
|
||||
use super::Skeleton;
|
||||
use crate::render::FigureBoneData;
|
||||
use vek::Vec3;
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct FixtureSkeleton;
|
||||
@ -15,7 +16,8 @@ impl Skeleton for FixtureSkeleton {
|
||||
|
||||
fn bone_count(&self) -> usize { 1 }
|
||||
|
||||
fn compute_matrices(&self) -> [FigureBoneData; 16] {
|
||||
fn compute_matrices(&self) -> ([FigureBoneData; 16], Vec3<f32>) {
|
||||
(
|
||||
[
|
||||
FigureBoneData::new(vek::Mat4::identity()), // <-- This is actually a bone!
|
||||
FigureBoneData::new(vek::Mat4::identity()),
|
||||
@ -33,7 +35,9 @@ impl Skeleton for FixtureSkeleton {
|
||||
FigureBoneData::new(vek::Mat4::identity()),
|
||||
FigureBoneData::new(vek::Mat4::identity()),
|
||||
FigureBoneData::new(vek::Mat4::identity()),
|
||||
]
|
||||
],
|
||||
Vec3::default(),
|
||||
)
|
||||
}
|
||||
|
||||
fn interpolate(&mut self, _target: &Self, _dt: f32) {}
|
||||
|
@ -8,6 +8,7 @@ pub use self::{idle::IdleAnimation, jump::JumpAnimation, run::RunAnimation};
|
||||
use super::{Bone, Skeleton};
|
||||
use crate::render::FigureBoneData;
|
||||
use common::comp::{self};
|
||||
use vek::Vec3;
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct GolemSkeleton {
|
||||
@ -45,7 +46,7 @@ impl GolemSkeleton {
|
||||
impl Skeleton for GolemSkeleton {
|
||||
type Attr = SkeletonAttr;
|
||||
|
||||
fn compute_matrices(&self) -> [FigureBoneData; 16] {
|
||||
fn compute_matrices(&self) -> ([FigureBoneData; 16], Vec3<f32>) {
|
||||
let upper_torso_mat = self.upper_torso.compute_base_matrix();
|
||||
let shoulder_l_mat = self.shoulder_l.compute_base_matrix();
|
||||
let shoulder_r_mat = self.shoulder_r.compute_base_matrix();
|
||||
@ -54,13 +55,18 @@ impl Skeleton for GolemSkeleton {
|
||||
let torso_mat = self.torso.compute_base_matrix();
|
||||
let foot_l_mat = self.foot_l.compute_base_matrix();
|
||||
let foot_r_mat = self.foot_r.compute_base_matrix();
|
||||
(
|
||||
[
|
||||
FigureBoneData::new(torso_mat * upper_torso_mat * self.head.compute_base_matrix()),
|
||||
FigureBoneData::new(torso_mat * upper_torso_mat),
|
||||
FigureBoneData::new(torso_mat * upper_torso_mat * shoulder_l_mat),
|
||||
FigureBoneData::new(torso_mat * upper_torso_mat * shoulder_r_mat),
|
||||
FigureBoneData::new(torso_mat * upper_torso_mat * self.hand_l.compute_base_matrix()),
|
||||
FigureBoneData::new(torso_mat * upper_torso_mat * self.hand_r.compute_base_matrix()),
|
||||
FigureBoneData::new(
|
||||
torso_mat * upper_torso_mat * self.hand_l.compute_base_matrix(),
|
||||
),
|
||||
FigureBoneData::new(
|
||||
torso_mat * upper_torso_mat * self.hand_r.compute_base_matrix(),
|
||||
),
|
||||
FigureBoneData::new(foot_l_mat * leg_l_mat),
|
||||
FigureBoneData::new(foot_r_mat * leg_r_mat),
|
||||
FigureBoneData::new(foot_l_mat),
|
||||
@ -71,7 +77,9 @@ impl Skeleton for GolemSkeleton {
|
||||
FigureBoneData::default(),
|
||||
FigureBoneData::default(),
|
||||
FigureBoneData::default(),
|
||||
]
|
||||
],
|
||||
Vec3::default(),
|
||||
)
|
||||
}
|
||||
|
||||
fn interpolate(&mut self, target: &Self, dt: f32) {
|
||||
|
@ -54,7 +54,7 @@ pub trait Skeleton: Send + Sync + 'static {
|
||||
|
||||
fn bone_count(&self) -> usize { 16 }
|
||||
|
||||
fn compute_matrices(&self) -> [FigureBoneData; 16];
|
||||
fn compute_matrices(&self) -> ([FigureBoneData; 16], Vec3<f32>);
|
||||
|
||||
/// Change the current skeleton to be more like `target`.
|
||||
fn interpolate(&mut self, target: &Self, dt: f32);
|
||||
|
@ -17,7 +17,8 @@ impl Skeleton for ObjectSkeleton {
|
||||
|
||||
fn bone_count(&self) -> usize { 1 }
|
||||
|
||||
fn compute_matrices(&self) -> [FigureBoneData; 16] {
|
||||
fn compute_matrices(&self) -> ([FigureBoneData; 16], Vec3<f32>) {
|
||||
(
|
||||
[
|
||||
FigureBoneData::new(Mat4::scaling_3d(Vec3::broadcast(SCALE))),
|
||||
FigureBoneData::new(vek::Mat4::identity()),
|
||||
@ -35,7 +36,9 @@ impl Skeleton for ObjectSkeleton {
|
||||
FigureBoneData::new(vek::Mat4::identity()),
|
||||
FigureBoneData::new(vek::Mat4::identity()),
|
||||
FigureBoneData::new(vek::Mat4::identity()),
|
||||
]
|
||||
],
|
||||
Vec3::default(),
|
||||
)
|
||||
}
|
||||
|
||||
fn interpolate(&mut self, _target: &Self, _dt: f32) {}
|
||||
|
@ -8,6 +8,7 @@ pub use self::{idle::IdleAnimation, jump::JumpAnimation, run::RunAnimation};
|
||||
use super::{Bone, Skeleton};
|
||||
use crate::render::FigureBoneData;
|
||||
use common::comp::{self};
|
||||
use vek::Vec3;
|
||||
|
||||
#[derive(Clone, Default)]
|
||||
pub struct QuadrupedMediumSkeleton {
|
||||
@ -33,11 +34,12 @@ impl Skeleton for QuadrupedMediumSkeleton {
|
||||
|
||||
fn bone_count(&self) -> usize { 11 }
|
||||
|
||||
fn compute_matrices(&self) -> [FigureBoneData; 16] {
|
||||
fn compute_matrices(&self) -> ([FigureBoneData; 16], Vec3<f32>) {
|
||||
let ears_mat = self.ears.compute_base_matrix();
|
||||
let head_upper_mat = self.head_upper.compute_base_matrix();
|
||||
let head_lower_mat = self.head_lower.compute_base_matrix();
|
||||
let torso_mid_mat = self.torso_mid.compute_base_matrix();
|
||||
(
|
||||
[
|
||||
FigureBoneData::new(head_upper_mat),
|
||||
FigureBoneData::new(head_upper_mat * head_lower_mat),
|
||||
@ -55,7 +57,9 @@ impl Skeleton for QuadrupedMediumSkeleton {
|
||||
FigureBoneData::default(),
|
||||
FigureBoneData::default(),
|
||||
FigureBoneData::default(),
|
||||
]
|
||||
],
|
||||
Vec3::default(),
|
||||
)
|
||||
}
|
||||
|
||||
fn interpolate(&mut self, target: &Self, dt: f32) {
|
||||
|
@ -8,6 +8,7 @@ pub use self::{idle::IdleAnimation, jump::JumpAnimation, run::RunAnimation};
|
||||
use super::{Bone, Skeleton};
|
||||
use crate::render::FigureBoneData;
|
||||
use common::comp::{self};
|
||||
use vek::Vec3;
|
||||
|
||||
#[derive(Clone, Default)]
|
||||
pub struct QuadrupedSmallSkeleton {
|
||||
@ -28,7 +29,8 @@ impl Skeleton for QuadrupedSmallSkeleton {
|
||||
|
||||
fn bone_count(&self) -> usize { 6 }
|
||||
|
||||
fn compute_matrices(&self) -> [FigureBoneData; 16] {
|
||||
fn compute_matrices(&self) -> ([FigureBoneData; 16], Vec3<f32>) {
|
||||
(
|
||||
[
|
||||
FigureBoneData::new(self.head.compute_base_matrix()),
|
||||
FigureBoneData::new(self.chest.compute_base_matrix()),
|
||||
@ -46,7 +48,9 @@ impl Skeleton for QuadrupedSmallSkeleton {
|
||||
FigureBoneData::default(),
|
||||
FigureBoneData::default(),
|
||||
FigureBoneData::default(),
|
||||
]
|
||||
],
|
||||
Vec3::default(),
|
||||
)
|
||||
}
|
||||
|
||||
fn interpolate(&mut self, target: &Self, dt: f32) {
|
||||
|
@ -106,6 +106,9 @@ impl From<&crate::settings::GamepadSettings> for ControllerSettings {
|
||||
/*map.entry(settings.game_buttons.wall_leap)
|
||||
.or_default()
|
||||
.push(GameInput::WallLeap);*/
|
||||
map.entry(settings.game_buttons.toggle_lantern)
|
||||
.or_default()
|
||||
.push(GameInput::ToggleLantern);
|
||||
map.entry(settings.game_buttons.mount)
|
||||
.or_default()
|
||||
.push(GameInput::Mount);
|
||||
|
@ -4,7 +4,7 @@ use common::{
|
||||
comp::item::{
|
||||
armor::Armor,
|
||||
tool::{Tool, ToolKind},
|
||||
Consumable, Ingredient, Item, ItemKind, Lantern, Utility,
|
||||
Consumable, Ingredient, Item, ItemKind, Lantern, LanternKind, Utility,
|
||||
},
|
||||
figure::Segment,
|
||||
};
|
||||
@ -20,7 +20,7 @@ use vek::*;
|
||||
#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
|
||||
pub enum ItemKey {
|
||||
Tool(ToolKind),
|
||||
Lantern(Lantern),
|
||||
Lantern(LanternKind),
|
||||
Armor(Armor),
|
||||
Utility(Utility),
|
||||
Consumable(Consumable),
|
||||
@ -31,7 +31,7 @@ impl From<&Item> for ItemKey {
|
||||
fn from(item: &Item) -> Self {
|
||||
match &item.kind {
|
||||
ItemKind::Tool(Tool { kind, .. }) => ItemKey::Tool(kind.clone()),
|
||||
ItemKind::Lantern(kind) => ItemKey::Lantern(kind.clone()),
|
||||
ItemKind::Lantern(Lantern { kind, .. }) => ItemKey::Lantern(kind.clone()),
|
||||
ItemKind::Armor { kind, .. } => ItemKey::Armor(kind.clone()),
|
||||
ItemKind::Utility { kind, .. } => ItemKey::Utility(kind.clone()),
|
||||
ItemKind::Consumable { kind, .. } => ItemKey::Consumable(kind.clone()),
|
||||
|
@ -12,7 +12,7 @@ use common::{
|
||||
item::{
|
||||
armor::{Armor, Back, Belt, Chest, Foot, Hand, Head, Pants, Shoulder, Tabard},
|
||||
tool::{Tool, ToolKind},
|
||||
ItemKind, Lantern,
|
||||
ItemKind, Lantern, LanternKind,
|
||||
},
|
||||
object,
|
||||
quadruped_medium::{BodyType as QMBodyType, Species as QMSpecies},
|
||||
@ -259,7 +259,7 @@ pub struct HumArmorFootSpec(ArmorVoxSpecMap<Foot, ArmorVoxSpec>);
|
||||
#[derive(Serialize, Deserialize)]
|
||||
pub struct HumMainWeaponSpec(HashMap<ToolKind, ArmorVoxSpec>);
|
||||
#[derive(Serialize, Deserialize)]
|
||||
pub struct HumArmorLanternSpec(ArmorVoxSpecMap<Lantern, ArmorVoxSpec>);
|
||||
pub struct HumArmorLanternSpec(ArmorVoxSpecMap<LanternKind, ArmorVoxSpec>);
|
||||
#[derive(Serialize, Deserialize)]
|
||||
pub struct HumArmorHeadSpec(ArmorVoxSpecMap<Head, ArmorVoxSpec>);
|
||||
#[derive(Serialize, Deserialize)]
|
||||
@ -810,12 +810,13 @@ impl HumArmorLanternSpec {
|
||||
loadout: &Loadout,
|
||||
generate_mesh: impl FnOnce(&Segment, Vec3<f32>) -> Mesh<FigurePipeline>,
|
||||
) -> Mesh<FigurePipeline> {
|
||||
let spec =
|
||||
if let Some(ItemKind::Lantern(lantern)) = loadout.lantern.as_ref().map(|i| &i.kind) {
|
||||
match self.0.map.get(&lantern) {
|
||||
let spec = if let Some(ItemKind::Lantern(Lantern { kind, .. })) =
|
||||
loadout.lantern.as_ref().map(|i| &i.kind)
|
||||
{
|
||||
match self.0.map.get(&kind) {
|
||||
Some(spec) => spec,
|
||||
None => {
|
||||
error!("No lantern specification exists for {:?}", lantern);
|
||||
error!("No lantern specification exists for {:?}", kind);
|
||||
return load_mesh("not_found", Vec3::new(-4.0, -3.5, 2.0), generate_mesh);
|
||||
},
|
||||
}
|
||||
|
@ -21,10 +21,10 @@ use crate::{
|
||||
};
|
||||
use common::{
|
||||
comp::{
|
||||
item::ItemKind, Body, CharacterState, Last, Loadout, Ori, PhysicsState, Pos, Scale, Stats,
|
||||
Vel,
|
||||
item::ItemKind, Body, CharacterState, Last, LightAnimation, LightEmitter, Loadout, Ori,
|
||||
PhysicsState, Pos, Scale, Stats, Vel,
|
||||
},
|
||||
state::State,
|
||||
state::{DeltaTime, State},
|
||||
states::triple_strike,
|
||||
terrain::TerrainChunk,
|
||||
vol::RectRasterableVol,
|
||||
@ -108,6 +108,61 @@ impl FigureMgr {
|
||||
self.golem_model_cache.clean(tick);
|
||||
}
|
||||
|
||||
pub fn update_lighting(&mut self, scene_data: &SceneData) {
|
||||
let ecs = scene_data.state.ecs();
|
||||
for (entity, light_emitter) in (&ecs.entities(), &ecs.read_storage::<LightEmitter>()).join()
|
||||
{
|
||||
// Add LightAnimation for objects with a LightEmitter
|
||||
let mut anim_storage = ecs.write_storage::<LightAnimation>();
|
||||
if let None = anim_storage.get_mut(entity) {
|
||||
let anim = LightAnimation {
|
||||
offset: Vec3::zero(),
|
||||
col: light_emitter.col,
|
||||
strength: 0.0,
|
||||
};
|
||||
let _ = anim_storage.insert(entity, anim);
|
||||
}
|
||||
}
|
||||
let dt = ecs.fetch::<DeltaTime>().0;
|
||||
for (entity, waypoint, light_emitter_opt, light_anim) in (
|
||||
&ecs.entities(),
|
||||
ecs.read_storage::<common::comp::Waypoint>().maybe(),
|
||||
ecs.read_storage::<LightEmitter>().maybe(),
|
||||
&mut ecs.write_storage::<LightAnimation>(),
|
||||
)
|
||||
.join()
|
||||
{
|
||||
let (target_col, target_strength, flicker, animated) =
|
||||
if let Some(emitter) = light_emitter_opt {
|
||||
(
|
||||
emitter.col,
|
||||
emitter.strength,
|
||||
emitter.flicker,
|
||||
emitter.animated,
|
||||
)
|
||||
} else {
|
||||
(Rgb::zero(), 0.0, 0.0, true)
|
||||
};
|
||||
if let Some(_) = waypoint {
|
||||
light_anim.offset = Vec3::unit_z() * 0.5;
|
||||
}
|
||||
if let Some(state) = self.character_states.get(&entity) {
|
||||
light_anim.offset = state.lantern_offset;
|
||||
}
|
||||
if animated {
|
||||
let flicker = (rand::random::<f32>() - 0.5) * flicker / dt.sqrt();
|
||||
// Close gap between current and target strength by 95% per second
|
||||
let delta = 0.05_f32.powf(dt);
|
||||
light_anim.strength =
|
||||
light_anim.strength * delta + (target_strength + flicker) * (1.0 - delta);
|
||||
light_anim.col = light_anim.col * delta + target_col * (1.0 - delta)
|
||||
} else {
|
||||
light_anim.strength = target_strength;
|
||||
light_anim.col = target_col;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn maintain(&mut self, renderer: &mut Renderer, scene_data: &SceneData, camera: &Camera) {
|
||||
let state = scene_data.state;
|
||||
let time = state.get_time();
|
||||
@ -1463,6 +1518,9 @@ impl FigureMgr {
|
||||
}
|
||||
}
|
||||
|
||||
// Update lighting (lanterns) for figures
|
||||
self.update_lighting(scene_data);
|
||||
|
||||
// Clear states that have deleted entities.
|
||||
self.character_states
|
||||
.retain(|entity, _| ecs.entities().is_alive(*entity));
|
||||
@ -1932,6 +1990,7 @@ impl FigureMgr {
|
||||
pub struct FigureState<S: Skeleton> {
|
||||
bone_consts: Consts<FigureBoneData>,
|
||||
locals: Consts<FigureLocals>,
|
||||
lantern_offset: Vec3<f32>,
|
||||
state_time: f64,
|
||||
skeleton: S,
|
||||
last_ori: Vec3<f32>,
|
||||
@ -1941,11 +2000,11 @@ pub struct FigureState<S: Skeleton> {
|
||||
|
||||
impl<S: Skeleton> FigureState<S> {
|
||||
pub fn new(renderer: &mut Renderer, skeleton: S) -> Self {
|
||||
let (bone_consts, lantern_offset) = skeleton.compute_matrices();
|
||||
Self {
|
||||
bone_consts: renderer
|
||||
.create_consts(&skeleton.compute_matrices())
|
||||
.unwrap(),
|
||||
bone_consts: renderer.create_consts(&bone_consts).unwrap(),
|
||||
locals: renderer.create_consts(&[FigureLocals::default()]).unwrap(),
|
||||
lantern_offset,
|
||||
state_time: 0.0,
|
||||
skeleton,
|
||||
last_ori: Vec3::zero(),
|
||||
@ -1984,12 +2043,14 @@ impl<S: Skeleton> FigureState<S> {
|
||||
let locals = FigureLocals::new(mat, col, is_player);
|
||||
renderer.update_consts(&mut self.locals, &[locals]).unwrap();
|
||||
|
||||
let (new_bone_consts, lantern_offset) = self.skeleton.compute_matrices();
|
||||
renderer
|
||||
.update_consts(
|
||||
&mut self.bone_consts,
|
||||
&self.skeleton.compute_matrices()[0..self.skeleton.bone_count()],
|
||||
&new_bone_consts[0..self.skeleton.bone_count()],
|
||||
)
|
||||
.unwrap();
|
||||
self.lantern_offset = lantern_offset;
|
||||
}
|
||||
|
||||
pub fn locals(&self) -> &Consts<FigureLocals> { &self.locals }
|
||||
|
@ -270,14 +270,17 @@ impl Scene {
|
||||
.ecs()
|
||||
.read_storage::<crate::ecs::comp::Interpolated>()
|
||||
.maybe(),
|
||||
&scene_data.state.ecs().read_storage::<comp::LightEmitter>(),
|
||||
&scene_data
|
||||
.state
|
||||
.ecs()
|
||||
.read_storage::<comp::LightAnimation>(),
|
||||
)
|
||||
.join()
|
||||
.filter(|(pos, _, _, _)| {
|
||||
(pos.0.distance_squared(player_pos) as f32)
|
||||
< self.loaded_distance.powf(2.0) + LIGHT_DIST_RADIUS
|
||||
})
|
||||
.map(|(pos, ori, interpolated, light_emitter)| {
|
||||
.map(|(pos, ori, interpolated, light_anim)| {
|
||||
// Use interpolated values if they are available
|
||||
let (pos, ori) =
|
||||
interpolated.map_or((pos.0, ori.map(|o| o.0)), |i| (i.pos, Some(i.ori)));
|
||||
@ -289,9 +292,9 @@ impl Scene {
|
||||
}
|
||||
};
|
||||
Light::new(
|
||||
pos + (rot * light_emitter.offset),
|
||||
light_emitter.col,
|
||||
light_emitter.strength,
|
||||
pos + (rot * light_anim.offset),
|
||||
light_anim.col,
|
||||
light_anim.strength,
|
||||
)
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
|
@ -331,6 +331,9 @@ impl PlayState for SessionState {
|
||||
self.client.borrow_mut().swap_loadout();
|
||||
}
|
||||
}
|
||||
Event::InputUpdate(GameInput::ToggleLantern, true) => {
|
||||
self.client.borrow_mut().toggle_lantern();
|
||||
},
|
||||
Event::InputUpdate(GameInput::Mount, true) => {
|
||||
let mut client = self.client.borrow_mut();
|
||||
if client.is_mounted() {
|
||||
|
@ -120,6 +120,7 @@ impl ControlSettings {
|
||||
GameInput::Climb => KeyMouse::Key(VirtualKeyCode::Space),
|
||||
GameInput::ClimbDown => KeyMouse::Key(VirtualKeyCode::LControl),
|
||||
//GameInput::WallLeap => MIDDLE_CLICK_KEY,
|
||||
GameInput::ToggleLantern => KeyMouse::Key(VirtualKeyCode::G),
|
||||
GameInput::Mount => KeyMouse::Key(VirtualKeyCode::F),
|
||||
GameInput::Map => KeyMouse::Key(VirtualKeyCode::M),
|
||||
GameInput::Bag => KeyMouse::Key(VirtualKeyCode::B),
|
||||
@ -175,6 +176,7 @@ impl Default for ControlSettings {
|
||||
GameInput::Climb,
|
||||
GameInput::ClimbDown,
|
||||
//GameInput::WallLeap,
|
||||
GameInput::ToggleLantern,
|
||||
GameInput::Mount,
|
||||
GameInput::Enter,
|
||||
GameInput::Command,
|
||||
@ -275,6 +277,7 @@ pub mod con_settings {
|
||||
pub climb: Button,
|
||||
pub climb_down: Button,
|
||||
//pub wall_leap: Button,
|
||||
pub toggle_lantern: Button,
|
||||
pub mount: Button,
|
||||
pub map: Button,
|
||||
pub bag: Button,
|
||||
@ -361,6 +364,7 @@ pub mod con_settings {
|
||||
climb: Button::Simple(GilButton::South),
|
||||
climb_down: Button::Simple(GilButton::Unknown),
|
||||
//wall_leap: Button::Simple(GilButton::Unknown),
|
||||
toggle_lantern: Button::Simple(GilButton::East),
|
||||
mount: Button::Simple(GilButton::North),
|
||||
map: Button::Simple(GilButton::DPadRight),
|
||||
bag: Button::Simple(GilButton::DPadDown),
|
||||
|
@ -38,6 +38,7 @@ pub enum GameInput {
|
||||
Climb,
|
||||
ClimbDown,
|
||||
//WallLeap,
|
||||
ToggleLantern,
|
||||
Mount,
|
||||
Enter,
|
||||
Command,
|
||||
@ -78,6 +79,7 @@ impl GameInput {
|
||||
GameInput::Climb => "gameinput.climb",
|
||||
GameInput::ClimbDown => "gameinput.climbdown",
|
||||
//GameInput::WallLeap => "gameinput.wallleap",
|
||||
GameInput::ToggleLantern => "gameinput.togglelantern",
|
||||
GameInput::Mount => "gameinput.mount",
|
||||
GameInput::Enter => "gameinput.enter",
|
||||
GameInput::Command => "gameinput.command",
|
||||
|
Loading…
Reference in New Issue
Block a user