Equipped lanterns now provide an illumination effect.

This commit is contained in:
CapsizeGlimmer 2020-05-04 15:15:31 +00:00 committed by Monty Marz
parent 40ab94673e
commit 4e7f8c686a
52 changed files with 689 additions and 351 deletions

View File

@ -9,6 +9,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Added ### Added
- Player now starts with a lantern. Equipping/unequipping a lantern has the same effect as the `/lantern` command
- Added music system - Added music system
- Added zoomable and rotatable minimap - Added zoomable and rotatable minimap
- Added rotating orientation marker to main-map - Added rotating orientation marker to main-map

View File

@ -1,5 +1,12 @@
Item( Item(
name: "Black Lantern", name: "Black Lantern",
description: "Used by city guards.", 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,
),
),
) )

View 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,
),
),
)

View File

@ -1,5 +1,12 @@
Item( Item(
name: "Lime Zest Lantern", name: "Lime Zest Lantern",
description: "It has an opening that could fit a ring...", 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,
),
),
) )

View 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

Binary file not shown.

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

Binary file not shown.

View File

@ -316,6 +316,7 @@ Enjoy your stay in the World of Veloren."#,
"gameinput.climb": "Climb", "gameinput.climb": "Climb",
"gameinput.climbdown": "Climb Down", "gameinput.climbdown": "Climb Down",
"gameinput.wallleap": "Wall Leap", "gameinput.wallleap": "Wall Leap",
"gameinput.togglelantern": "Toggle Lantern",
"gameinput.mount": "Mount", "gameinput.mount": "Mount",
"gameinput.enter": "Enter", "gameinput.enter": "Enter",
"gameinput.command": "Command", "gameinput.command": "Command",

View File

@ -56,10 +56,16 @@
), ),
// Lanterns // Lanterns
Lantern(Black0): Png( Lantern(Black0): Png(
"element.icons.lantern_black-0", "element.icons.lantern_black-0",
), ),
Lantern(Green0): Png( Lantern(Green0): Png(
"element.icons.lantern_green-0", "element.icons.lantern_green-0",
),
Lantern(Blue0): Png(
"element.icons.lantern_blue-0",
),
Lantern(Red0): Png(
"element.icons.lantern_red-0",
), ),
// Farming Equipment // Farming Equipment
Tool(Farming(Broom)): VoxTrans( Tool(Farming(Broom)): VoxTrans(

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

Binary file not shown.

View File

@ -7,10 +7,18 @@
Green0: ( Green0: (
vox_spec: ("armor.lantern.green-0", (-2.0, -2.0, -7.0)), vox_spec: ("armor.lantern.green-0", (-2.0, -2.0, -7.0)),
color: None color: None
), ),
Black0: ( Black0: (
vox_spec: ("armor.lantern.black-0", (-2.0, -2.0, -7.0)), vox_spec: ("armor.lantern.black-0", (-2.0, -2.0, -7.0)),
color: None 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
),
}, },
)) ))

View File

@ -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 { pub fn is_mounted(&self) -> bool {
self.state self.state
.ecs() .ecs()

View File

@ -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> { pub fn load_expect<A: Asset + 'static>(specifier: &str) -> Arc<A> {
load(specifier).unwrap_or_else(|err| { load(specifier).unwrap_or_else(|err| {
panic!( panic!(
"Failed loading essential asset: {} (error={})", "Failed loading essential asset: {} (error={:?})",
specifier, err specifier, err
) )
}) })

View File

@ -18,6 +18,7 @@ pub enum InventoryManip {
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] #[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
pub enum ControlEvent { pub enum ControlEvent {
ToggleLantern,
Mount(Uid), Mount(Uid),
Unmount, Unmount,
InventoryManip(InventoryManip), InventoryManip(InventoryManip),

View File

@ -13,6 +13,7 @@ use rand::seq::SliceRandom;
use specs::{Component, FlaggedStorage}; use specs::{Component, FlaggedStorage};
use specs_idvs::IDVStorage; use specs_idvs::IDVStorage;
use std::{fs::File, io::BufReader}; use std::{fs::File, io::BufReader};
use vek::Rgb;
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)] #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub enum Consumable { pub enum Consumable {
@ -39,11 +40,33 @@ pub enum Ingredient {
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)] #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
#[repr(u32)] #[repr(u32)]
pub enum Lantern { pub enum LanternKind {
Black0 = 1, Black0 = 1,
Green0 = 2, 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 } fn default_amount() -> u32 { 1 }

View File

@ -3,6 +3,7 @@ pub mod slot;
use crate::assets; use crate::assets;
use item::{Consumable, Item, ItemKind}; use item::{Consumable, Item, ItemKind};
use rand::{seq::SliceRandom, thread_rng};
use specs::{Component, FlaggedStorage, HashMapStorage}; use specs::{Component, FlaggedStorage, HashMapStorage};
use specs_idvs::IDVStorage; use specs_idvs::IDVStorage;
use std::ops::Not; 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.cheese"));
inventory.push(assets::load_expect_cloned("common.items.apple")); 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 inventory
} }
} }

View File

@ -6,9 +6,9 @@ lazy_static! {
assets::load_expect_cloned("common.items.debug.possess") 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] #[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. /// Attempting to push into a full inventory should return the same item.
#[test] #[test]

View File

@ -39,4 +39,4 @@ pub use phys::{Collider, ForceUpdate, Gravity, Mass, Ori, PhysicsState, Pos, Sca
pub use player::Player; pub use player::Player;
pub use projectile::Projectile; pub use projectile::Projectile;
pub use stats::{Exp, HealthChange, HealthSource, Level, Stats}; pub use stats::{Exp, HealthChange, HealthSource, Level, Stats};
pub use visual::LightEmitter; pub use visual::{LightAnimation, LightEmitter};

View File

@ -4,17 +4,19 @@ use vek::*;
#[derive(Copy, Clone, Debug, PartialEq, Serialize, Deserialize)] #[derive(Copy, Clone, Debug, PartialEq, Serialize, Deserialize)]
pub struct LightEmitter { pub struct LightEmitter {
pub offset: Vec3<f32>,
pub col: Rgb<f32>, pub col: Rgb<f32>,
pub strength: f32, pub strength: f32,
pub flicker: f32,
pub animated: bool,
} }
impl Default for LightEmitter { impl Default for LightEmitter {
fn default() -> Self { fn default() -> Self {
Self { Self {
offset: Vec3::zero(),
col: Rgb::one(), col: Rgb::one(),
strength: 1.0, strength: 1.0,
flicker: 0.0,
animated: false,
} }
} }
} }
@ -22,3 +24,24 @@ impl Default for LightEmitter {
impl Component for LightEmitter { impl Component for LightEmitter {
type Storage = FlaggedStorage<Self, IDVStorage<Self>>; 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>>;
}

View File

@ -86,6 +86,7 @@ pub enum ServerEvent {
entity: EcsEntity, entity: EcsEntity,
vel: Vec3<f32>, vel: Vec3<f32>,
}, },
ToggleLantern(EcsEntity),
Mount(EcsEntity, EcsEntity), Mount(EcsEntity, EcsEntity),
Unmount(EcsEntity), Unmount(EcsEntity),
Possess(Uid, Uid), Possess(Uid, Uid),

View File

@ -135,6 +135,10 @@ impl State {
ecs.register::<comp::Ori>(); ecs.register::<comp::Ori>();
ecs.register::<comp::Inventory>(); ecs.register::<comp::Inventory>();
// Register client-local components
// TODO: only register on the client
ecs.register::<comp::LightAnimation>();
// Register server-local components // Register server-local components
// TODO: only register on the server // TODO: only register on the server
ecs.register::<comp::Last<comp::Pos>>(); ecs.register::<comp::Last<comp::Pos>>();

View File

@ -74,6 +74,9 @@ impl<'a> System<'a> for Sys {
} }
}, },
ControlEvent::Unmount => server_emitter.emit(ServerEvent::Unmount(entity)), ControlEvent::Unmount => server_emitter.emit(ServerEvent::Unmount(entity)),
ControlEvent::ToggleLantern => {
server_emitter.emit(ServerEvent::ToggleLantern(entity))
},
ControlEvent::InventoryManip(manip) => { ControlEvent::InventoryManip(manip) => {
*character_state = CharacterState::Idle; *character_state = CharacterState::Idle;
server_emitter.emit(ServerEvent::InventoryManip(entity, manip)) server_emitter.emit(ServerEvent::InventoryManip(entity, manip))

View File

@ -202,9 +202,9 @@ lazy_static! {
), ),
ChatCommand::new( ChatCommand::new(
"lantern", "lantern",
"{}", "{} {} {} {}",
"/lantern : adds/remove light near player", "/lantern <strength> [<r> <g> <b>]: Change your lantern's strength and color",
false, true,
handle_lantern, handle_lantern,
), ),
ChatCommand::new( ChatCommand::new(
@ -847,6 +847,7 @@ fn handle_light(
scan_fmt_some!(&args, action.arg_fmt, f32, f32, f32, f32, f32, f32, f32); scan_fmt_some!(&args, action.arg_fmt, f32, f32, f32, f32, f32, f32, f32);
let mut light_emitter = comp::LightEmitter::default(); 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) { if let (Some(r), Some(g), Some(b)) = (opt_r, opt_g, opt_b) {
let r = r.max(0.0).min(1.0); let r = r.max(0.0).min(1.0);
@ -855,7 +856,11 @@ fn handle_light(
light_emitter.col = Rgb::new(r, g, b) light_emitter.col = Rgb::new(r, g, b)
}; };
if let (Some(x), Some(y), Some(z)) = (opt_x, opt_y, opt_z) { 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 { if let Some(s) = opt_s {
light_emitter.strength = s.max(0.0) light_emitter.strength = s.max(0.0)
@ -867,14 +872,18 @@ fn handle_light(
.get(target) .get(target)
.copied(); .copied();
if let Some(pos) = pos { if let Some(pos) = pos {
server let builder = server
.state .state
.ecs_mut() .ecs_mut()
.create_entity_synced() .create_entity_synced()
.with(pos) .with(pos)
.with(comp::ForceUpdate) .with(comp::ForceUpdate)
.with(light_emitter) .with(light_emitter);
.build(); 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."))); server.notify_client(client, ServerMsg::private(format!("Spawned object.")));
} else { } else {
server.notify_client(client, ServerMsg::private(format!("You have no position!"))); server.notify_client(client, ServerMsg::private(format!("You have no position!")));
@ -888,57 +897,39 @@ fn handle_lantern(
args: String, args: String,
action: &ChatCommand, action: &ChatCommand,
) { ) {
let opt_s = scan_fmt_some!(&args, action.arg_fmt, f32); if let (Some(s), r, g, b) = scan_fmt_some!(&args, action.arg_fmt, f32, f32, f32, f32) {
if let Some(light) = server
if server .state
.state .ecs()
.read_storage::<comp::LightEmitter>() .write_storage::<comp::LightEmitter>()
.get(target) .get_mut(target)
.is_some() {
{ light.strength = s.max(0.1).min(10.0);
if let Some(s) = opt_s { if let (Some(r), Some(g), Some(b)) = (r, g, b) {
if let Some(light) = server light.col = (
.state r.max(0.0).min(1.0),
.ecs() g.max(0.0).min(1.0),
.write_storage::<comp::LightEmitter>() b.max(0.0).min(1.0),
.get_mut(target) )
{ .into();
light.strength = s.max(0.1).min(10.0); server.notify_client(
client,
ServerMsg::private(String::from("You adjusted flame strength and color.")),
);
} else {
server.notify_client( server.notify_client(
client, client,
ServerMsg::private(String::from("You adjusted flame strength.")), ServerMsg::private(String::from("You adjusted flame strength.")),
); );
} }
} else { } else {
server
.state
.ecs()
.write_storage::<comp::LightEmitter>()
.remove(target);
server.notify_client( server.notify_client(
client, client,
ServerMsg::private(String::from("You put out the lantern.")), ServerMsg::private(String::from("Please equip a lantern first")),
); );
} }
} else { } else {
let _ = server server.notify_client(client, ServerMsg::private(String::from(action.help_string)));
.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.")),
);
} }
} }

View File

@ -79,9 +79,10 @@ pub fn handle_create_waypoint(server: &mut Server, pos: Vec3<f32>) {
.state .state
.create_object(Pos(pos), comp::object::Body::CampfireLit) .create_object(Pos(pos), comp::object::Body::CampfireLit)
.with(LightEmitter { .with(LightEmitter {
offset: Vec3::unit_z() * 0.5,
col: Rgb::new(1.0, 0.65, 0.2), col: Rgb::new(1.0, 0.65, 0.2),
strength: 2.0, strength: 2.0,
flicker: 1.0,
animated: true,
}) })
.with(WaypointArea::default()) .with(WaypointArea::default())
.build(); .build();

View File

@ -86,6 +86,10 @@ pub fn handle_destroy(server: &mut Server, entity: EcsEntity, cause: HealthSourc
.insert(entity, comp::ForceUpdate) .insert(entity, comp::ForceUpdate)
.err() .err()
.map(|err| error!("Failed to insert ForceUpdate on dead client: {:?}", err)); .map(|err| error!("Failed to insert ForceUpdate on dead client: {:?}", err));
state
.ecs()
.write_storage::<comp::LightEmitter>()
.remove(entity);
state state
.ecs() .ecs()
.write_storage::<comp::Energy>() .write_storage::<comp::Energy>()

View File

@ -11,6 +11,43 @@ use common::{
use log::error; use log::error;
use specs::{world::WorldExt, Entity as EcsEntity}; 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) { pub fn handle_mount(server: &mut Server, mounter: EcsEntity, mountee: EcsEntity) {
let state = server.state_mut(); let state = server.state_mut();

View File

@ -11,9 +11,24 @@ use common::{
}; };
use log::error; use log::error;
use rand::Rng; 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; 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) { pub fn handle_inventory(server: &mut Server, entity: EcsEntity, manip: comp::InventoryManip) {
let state = server.state_mut(); let state = server.state_mut();
let mut dropped_items = Vec::new(); 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 { let event = match slot {
Slot::Inventory(slot) => { Slot::Inventory(slot) => {
use item::ItemKind; use item::ItemKind;
// Check if item is equipable let (is_equippable, lantern_opt) =
if inventory.get(slot).map_or(false, |i| match &i.kind { inventory
ItemKind::Tool(_) | ItemKind::Armor { .. } | ItemKind::Lantern(_) => true, .get(slot)
_ => false, .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(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); slot::equip(slot, inventory, loadout);
Some(comp::InventoryUpdateEvent::Used) Some(comp::InventoryUpdateEvent::Used)
} else { } else {
@ -191,6 +213,9 @@ pub fn handle_inventory(server: &mut Server, entity: EcsEntity, manip: comp::Inv
}, },
Slot::Equip(slot) => { Slot::Equip(slot) => {
if let Some(loadout) = state.ecs().write_storage().get_mut(entity) { 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); slot::unequip(slot, inventory, loadout);
Some(comp::InventoryUpdateEvent::Used) Some(comp::InventoryUpdateEvent::Used)
} else { } else {

View File

@ -6,7 +6,7 @@ use entity_creation::{
use entity_manipulation::{ use entity_manipulation::{
handle_damage, handle_destroy, handle_explosion, handle_land_on_ground, handle_respawn, 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 inventory_manip::handle_inventory;
use player::{handle_client_disconnect, handle_exit_ingame}; use player::{handle_client_disconnect, handle_exit_ingame};
use specs::{Entity as EcsEntity, WorldExt}; use specs::{Entity as EcsEntity, WorldExt};
@ -63,6 +63,7 @@ impl Server {
ServerEvent::LandOnGround { entity, vel } => { ServerEvent::LandOnGround { entity, vel } => {
handle_land_on_ground(&self, 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::Mount(mounter, mountee) => handle_mount(self, mounter, mountee),
ServerEvent::Unmount(mounter) => handle_unmount(self, mounter), ServerEvent::Unmount(mounter) => handle_unmount(self, mounter),
ServerEvent::Possess(possessor_uid, possesse_uid) => { ServerEvent::Possess(possessor_uid, possesse_uid) => {

View File

@ -127,7 +127,6 @@ impl StateExt for State {
z_max: 0.9, z_max: 0.9,
}) })
.with(comp::Gravity(1.0)) .with(comp::Gravity(1.0))
//.with(comp::LightEmitter::default())
} }
/// Build a projectile /// Build a projectile

View File

@ -8,6 +8,7 @@ pub use self::{idle::IdleAnimation, jump::JumpAnimation, run::RunAnimation};
use super::{Bone, Skeleton}; use super::{Bone, Skeleton};
use crate::render::FigureBoneData; use crate::render::FigureBoneData;
use common::comp::{self}; use common::comp::{self};
use vek::Vec3;
#[derive(Clone)] #[derive(Clone)]
pub struct BipedLargeSkeleton { pub struct BipedLargeSkeleton {
@ -49,7 +50,7 @@ impl Skeleton for BipedLargeSkeleton {
fn bone_count(&self) -> usize { 11 } 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 upper_torso_mat = self.upper_torso.compute_base_matrix();
let shoulder_l_mat = self.shoulder_l.compute_base_matrix(); let shoulder_l_mat = self.shoulder_l.compute_base_matrix();
let shoulder_r_mat = self.shoulder_r.compute_base_matrix(); let shoulder_r_mat = self.shoulder_r.compute_base_matrix();
@ -57,26 +58,33 @@ impl Skeleton for BipedLargeSkeleton {
let leg_r_mat = self.leg_r.compute_base_matrix(); let leg_r_mat = self.leg_r.compute_base_matrix();
let torso_mat = self.torso.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), FigureBoneData::new(torso_mat * upper_torso_mat * self.head.compute_base_matrix()),
FigureBoneData::new( FigureBoneData::new(torso_mat * upper_torso_mat),
torso_mat * upper_torso_mat * self.lower_torso.compute_base_matrix(), FigureBoneData::new(
), torso_mat * upper_torso_mat * self.lower_torso.compute_base_matrix(),
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 * shoulder_l_mat),
FigureBoneData::new(torso_mat * upper_torso_mat * self.hand_l.compute_base_matrix()), FigureBoneData::new(torso_mat * upper_torso_mat * shoulder_r_mat),
FigureBoneData::new(torso_mat * upper_torso_mat * self.hand_r.compute_base_matrix()), FigureBoneData::new(
FigureBoneData::new(torso_mat * upper_torso_mat * leg_l_mat), torso_mat * upper_torso_mat * self.hand_l.compute_base_matrix(),
FigureBoneData::new(torso_mat * upper_torso_mat * leg_r_mat), ),
FigureBoneData::new(self.foot_l.compute_base_matrix()), FigureBoneData::new(
FigureBoneData::new(self.foot_r.compute_base_matrix()), torso_mat * upper_torso_mat * self.hand_r.compute_base_matrix(),
FigureBoneData::default(), ),
FigureBoneData::default(), FigureBoneData::new(torso_mat * upper_torso_mat * leg_l_mat),
FigureBoneData::default(), FigureBoneData::new(torso_mat * upper_torso_mat * leg_r_mat),
FigureBoneData::default(), FigureBoneData::new(self.foot_l.compute_base_matrix()),
FigureBoneData::default(), FigureBoneData::new(self.foot_r.compute_base_matrix()),
] FigureBoneData::default(),
FigureBoneData::default(),
FigureBoneData::default(),
FigureBoneData::default(),
FigureBoneData::default(),
],
Vec3::default(),
)
} }
fn interpolate(&mut self, target: &Self, dt: f32) { fn interpolate(&mut self, target: &Self, dt: f32) {

View File

@ -8,6 +8,7 @@ pub use self::{fly::FlyAnimation, idle::IdleAnimation, run::RunAnimation};
use super::{Bone, Skeleton}; use super::{Bone, Skeleton};
use crate::render::FigureBoneData; use crate::render::FigureBoneData;
use common::comp::{self}; use common::comp::{self};
use vek::Vec3;
#[derive(Clone, Default)] #[derive(Clone, Default)]
pub struct BirdMediumSkeleton { pub struct BirdMediumSkeleton {
@ -29,27 +30,30 @@ impl Skeleton for BirdMediumSkeleton {
fn bone_count(&self) -> usize { 7 } 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(); let torso_mat = self.torso.compute_base_matrix();
[ (
FigureBoneData::new(torso_mat * self.head.compute_base_matrix()), [
FigureBoneData::new(torso_mat), FigureBoneData::new(torso_mat * self.head.compute_base_matrix()),
FigureBoneData::new(torso_mat * self.tail.compute_base_matrix()), FigureBoneData::new(torso_mat),
FigureBoneData::new(torso_mat * self.wing_l.compute_base_matrix()), FigureBoneData::new(torso_mat * self.tail.compute_base_matrix()),
FigureBoneData::new(torso_mat * self.wing_r.compute_base_matrix()), FigureBoneData::new(torso_mat * self.wing_l.compute_base_matrix()),
FigureBoneData::new(self.leg_l.compute_base_matrix()), FigureBoneData::new(torso_mat * self.wing_r.compute_base_matrix()),
FigureBoneData::new(self.leg_r.compute_base_matrix()), FigureBoneData::new(self.leg_l.compute_base_matrix()),
FigureBoneData::default(), FigureBoneData::new(self.leg_r.compute_base_matrix()),
FigureBoneData::default(), FigureBoneData::default(),
FigureBoneData::default(), FigureBoneData::default(),
FigureBoneData::default(), FigureBoneData::default(),
FigureBoneData::default(), FigureBoneData::default(),
FigureBoneData::default(), FigureBoneData::default(),
FigureBoneData::default(), FigureBoneData::default(),
FigureBoneData::default(), FigureBoneData::default(),
FigureBoneData::default(), FigureBoneData::default(),
] FigureBoneData::default(),
],
Vec3::default(),
)
} }
fn interpolate(&mut self, target: &Self, dt: f32) { fn interpolate(&mut self, target: &Self, dt: f32) {

View File

@ -8,6 +8,7 @@ pub use self::{idle::IdleAnimation, jump::JumpAnimation, run::RunAnimation};
use super::{Bone, Skeleton}; use super::{Bone, Skeleton};
use crate::render::FigureBoneData; use crate::render::FigureBoneData;
use common::comp::{self}; use common::comp::{self};
use vek::Vec3;
#[derive(Clone)] #[derive(Clone)]
pub struct BirdSmallSkeleton { pub struct BirdSmallSkeleton {
@ -33,27 +34,30 @@ impl Skeleton for BirdSmallSkeleton {
fn bone_count(&self) -> usize { 4 } 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(); let torso_mat = self.torso.compute_base_matrix();
[ (
FigureBoneData::new(self.head.compute_base_matrix() * torso_mat), [
FigureBoneData::new(torso_mat), FigureBoneData::new(self.head.compute_base_matrix() * torso_mat),
FigureBoneData::new(self.wing_l.compute_base_matrix() * torso_mat), FigureBoneData::new(torso_mat),
FigureBoneData::new(self.wing_r.compute_base_matrix() * torso_mat), FigureBoneData::new(self.wing_l.compute_base_matrix() * torso_mat),
FigureBoneData::default(), FigureBoneData::new(self.wing_r.compute_base_matrix() * torso_mat),
FigureBoneData::default(), FigureBoneData::default(),
FigureBoneData::default(), FigureBoneData::default(),
FigureBoneData::default(), FigureBoneData::default(),
FigureBoneData::default(), FigureBoneData::default(),
FigureBoneData::default(), FigureBoneData::default(),
FigureBoneData::default(), FigureBoneData::default(),
FigureBoneData::default(), FigureBoneData::default(),
FigureBoneData::default(), FigureBoneData::default(),
FigureBoneData::default(), FigureBoneData::default(),
FigureBoneData::default(), FigureBoneData::default(),
FigureBoneData::default(), FigureBoneData::default(),
] FigureBoneData::default(),
],
Vec3::default(),
)
} }
fn interpolate(&mut self, target: &Self, dt: f32) { fn interpolate(&mut self, target: &Self, dt: f32) {

View File

@ -31,6 +31,7 @@ pub use self::{
use super::{Bone, Skeleton}; use super::{Bone, Skeleton};
use crate::render::FigureBoneData; use crate::render::FigureBoneData;
use common::comp; use common::comp;
use vek::{Vec3, Vec4};
#[derive(Clone, Default)] #[derive(Clone, Default)]
pub struct CharacterSkeleton { pub struct CharacterSkeleton {
@ -64,7 +65,7 @@ impl Skeleton for CharacterSkeleton {
fn bone_count(&self) -> usize { 15 } 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 chest_mat = self.chest.compute_base_matrix();
let torso_mat = self.torso.compute_base_matrix(); let torso_mat = self.torso.compute_base_matrix();
let l_hand_mat = self.l_hand.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 second_mat = self.second.compute_base_matrix();
let shorts_mat = self.shorts.compute_base_matrix(); let shorts_mat = self.shorts.compute_base_matrix();
let head_mat = self.head.compute_base_matrix(); let head_mat = self.head.compute_base_matrix();
[
FigureBoneData::new(torso_mat * chest_mat * head_mat), let lantern_final_mat =
FigureBoneData::new(torso_mat * chest_mat), torso_mat * chest_mat * shorts_mat * self.lantern.compute_base_matrix();
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 * head_mat),
FigureBoneData::new(torso_mat * chest_mat * control_mat * r_control_mat * r_hand_mat), FigureBoneData::new(torso_mat * chest_mat),
FigureBoneData::new(torso_mat * self.l_foot.compute_base_matrix()), FigureBoneData::new(torso_mat * chest_mat * self.belt.compute_base_matrix()),
FigureBoneData::new(torso_mat * self.r_foot.compute_base_matrix()), FigureBoneData::new(torso_mat * chest_mat * self.back.compute_base_matrix()),
FigureBoneData::new(torso_mat * chest_mat * self.l_shoulder.compute_base_matrix()), FigureBoneData::new(torso_mat * chest_mat * shorts_mat),
FigureBoneData::new(torso_mat * chest_mat * self.r_shoulder.compute_base_matrix()), FigureBoneData::new(
FigureBoneData::new(torso_mat * self.glider.compute_base_matrix()), torso_mat * chest_mat * control_mat * l_control_mat * l_hand_mat,
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(
FigureBoneData::new( torso_mat * chest_mat * control_mat * r_control_mat * r_hand_mat,
torso_mat * chest_mat * shorts_mat * self.lantern.compute_base_matrix(), ),
), FigureBoneData::new(torso_mat * self.l_foot.compute_base_matrix()),
FigureBoneData::default(), 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(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) { fn interpolate(&mut self, target: &Self, dt: f32) {

View File

@ -8,6 +8,7 @@ pub use self::{idle::IdleAnimation, jump::JumpAnimation, run::RunAnimation};
use super::{Bone, Skeleton}; use super::{Bone, Skeleton};
use crate::render::FigureBoneData; use crate::render::FigureBoneData;
use common::comp::{self}; use common::comp::{self};
use vek::Vec3;
#[derive(Clone, Default)] #[derive(Clone, Default)]
pub struct CritterSkeleton { pub struct CritterSkeleton {
@ -34,25 +35,28 @@ impl Skeleton for CritterSkeleton {
fn bone_count(&self) -> usize { 5 } 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()), FigureBoneData::new(self.head.compute_base_matrix()),
FigureBoneData::new(self.feet_f.compute_base_matrix()), FigureBoneData::new(self.chest.compute_base_matrix()),
FigureBoneData::new(self.feet_b.compute_base_matrix()), FigureBoneData::new(self.feet_f.compute_base_matrix()),
FigureBoneData::new(self.tail.compute_base_matrix()), FigureBoneData::new(self.feet_b.compute_base_matrix()),
FigureBoneData::default(), FigureBoneData::new(self.tail.compute_base_matrix()),
FigureBoneData::default(), FigureBoneData::default(),
FigureBoneData::default(), FigureBoneData::default(),
FigureBoneData::default(), FigureBoneData::default(),
FigureBoneData::default(), FigureBoneData::default(),
FigureBoneData::default(), FigureBoneData::default(),
FigureBoneData::default(), FigureBoneData::default(),
FigureBoneData::default(), FigureBoneData::default(),
FigureBoneData::default(), FigureBoneData::default(),
FigureBoneData::default(), FigureBoneData::default(),
FigureBoneData::default(), FigureBoneData::default(),
] FigureBoneData::default(),
],
Vec3::default(),
)
} }
fn interpolate(&mut self, target: &Self, dt: f32) { fn interpolate(&mut self, target: &Self, dt: f32) {

View File

@ -8,6 +8,7 @@ pub use self::{idle::IdleAnimation, jump::JumpAnimation, run::RunAnimation};
use super::{Bone, Skeleton}; use super::{Bone, Skeleton};
use crate::render::FigureBoneData; use crate::render::FigureBoneData;
use common::comp::{self}; use common::comp::{self};
use vek::Vec3;
#[derive(Clone)] #[derive(Clone)]
pub struct DragonSkeleton { pub struct DragonSkeleton {
@ -51,30 +52,33 @@ impl Skeleton for DragonSkeleton {
fn bone_count(&self) -> usize { 13 } 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 chest_front_mat = self.chest_front.compute_base_matrix();
let wing_in_l_mat = self.wing_in_l.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 wing_in_r_mat = self.wing_in_r.compute_base_matrix();
let tail_front_mat = self.tail_front.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), FigureBoneData::new(self.head.compute_base_matrix() * chest_front_mat),
FigureBoneData::new(self.chest_rear.compute_base_matrix() * chest_front_mat), FigureBoneData::new(chest_front_mat),
FigureBoneData::new(tail_front_mat), FigureBoneData::new(self.chest_rear.compute_base_matrix() * chest_front_mat),
FigureBoneData::new(self.tail_rear.compute_base_matrix() * tail_front_mat), FigureBoneData::new(tail_front_mat),
FigureBoneData::new(wing_in_l_mat), FigureBoneData::new(self.tail_rear.compute_base_matrix() * tail_front_mat),
FigureBoneData::new(wing_in_r_mat), FigureBoneData::new(wing_in_l_mat),
FigureBoneData::new(self.wing_out_l.compute_base_matrix() * wing_in_l_mat), FigureBoneData::new(wing_in_r_mat),
FigureBoneData::new(self.wing_out_r.compute_base_matrix() * wing_in_r_mat), FigureBoneData::new(self.wing_out_l.compute_base_matrix() * wing_in_l_mat),
FigureBoneData::new(self.foot_fl.compute_base_matrix()), FigureBoneData::new(self.wing_out_r.compute_base_matrix() * wing_in_r_mat),
FigureBoneData::new(self.foot_fr.compute_base_matrix()), FigureBoneData::new(self.foot_fl.compute_base_matrix()),
FigureBoneData::new(self.foot_bl.compute_base_matrix()), FigureBoneData::new(self.foot_fr.compute_base_matrix()),
FigureBoneData::new(self.foot_br.compute_base_matrix()), FigureBoneData::new(self.foot_bl.compute_base_matrix()),
FigureBoneData::default(), FigureBoneData::new(self.foot_br.compute_base_matrix()),
FigureBoneData::default(), FigureBoneData::default(),
FigureBoneData::default(), FigureBoneData::default(),
] FigureBoneData::default(),
],
Vec3::default(),
)
} }
fn interpolate(&mut self, target: &Self, dt: f32) { fn interpolate(&mut self, target: &Self, dt: f32) {

View File

@ -8,6 +8,7 @@ pub use self::{idle::IdleAnimation, jump::JumpAnimation, run::RunAnimation};
use super::{Bone, Skeleton}; use super::{Bone, Skeleton};
use crate::render::FigureBoneData; use crate::render::FigureBoneData;
use common::comp::{self}; use common::comp::{self};
use vek::Vec3;
#[derive(Clone)] #[derive(Clone)]
pub struct FishMediumSkeleton { pub struct FishMediumSkeleton {
@ -37,28 +38,31 @@ impl Skeleton for FishMediumSkeleton {
fn bone_count(&self) -> usize { 6 } 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 torso_mat = self.torso.compute_base_matrix();
let rear_mat = self.rear.compute_base_matrix(); let rear_mat = self.rear.compute_base_matrix();
[ (
FigureBoneData::new(self.head.compute_base_matrix() * torso_mat), [
FigureBoneData::new(torso_mat), FigureBoneData::new(self.head.compute_base_matrix() * torso_mat),
FigureBoneData::new(rear_mat * torso_mat), FigureBoneData::new(torso_mat),
FigureBoneData::new(self.tail.compute_base_matrix() * rear_mat), FigureBoneData::new(rear_mat * torso_mat),
FigureBoneData::new(self.fin_l.compute_base_matrix() * rear_mat), FigureBoneData::new(self.tail.compute_base_matrix() * rear_mat),
FigureBoneData::new(self.fin_r.compute_base_matrix() * rear_mat), FigureBoneData::new(self.fin_l.compute_base_matrix() * rear_mat),
FigureBoneData::default(), FigureBoneData::new(self.fin_r.compute_base_matrix() * rear_mat),
FigureBoneData::default(), FigureBoneData::default(),
FigureBoneData::default(), FigureBoneData::default(),
FigureBoneData::default(), FigureBoneData::default(),
FigureBoneData::default(), FigureBoneData::default(),
FigureBoneData::default(), FigureBoneData::default(),
FigureBoneData::default(), FigureBoneData::default(),
FigureBoneData::default(), FigureBoneData::default(),
FigureBoneData::default(), FigureBoneData::default(),
FigureBoneData::default(), FigureBoneData::default(),
] FigureBoneData::default(),
],
Vec3::default(),
)
} }
fn interpolate(&mut self, target: &Self, dt: f32) { fn interpolate(&mut self, target: &Self, dt: f32) {

View File

@ -8,6 +8,7 @@ pub use self::{idle::IdleAnimation, jump::JumpAnimation, run::RunAnimation};
use super::{Bone, Skeleton}; use super::{Bone, Skeleton};
use crate::render::FigureBoneData; use crate::render::FigureBoneData;
use common::comp::{self}; use common::comp::{self};
use vek::Vec3;
#[derive(Clone)] #[derive(Clone)]
pub struct FishSmallSkeleton { pub struct FishSmallSkeleton {
@ -29,27 +30,30 @@ impl Skeleton for FishSmallSkeleton {
fn bone_count(&self) -> usize { 2 } 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(); let torso_mat = self.torso.compute_base_matrix();
[ (
FigureBoneData::new(torso_mat), [
FigureBoneData::new(self.tail.compute_base_matrix() * torso_mat), FigureBoneData::new(torso_mat),
FigureBoneData::default(), FigureBoneData::new(self.tail.compute_base_matrix() * torso_mat),
FigureBoneData::default(), FigureBoneData::default(),
FigureBoneData::default(), FigureBoneData::default(),
FigureBoneData::default(), FigureBoneData::default(),
FigureBoneData::default(), FigureBoneData::default(),
FigureBoneData::default(), FigureBoneData::default(),
FigureBoneData::default(), FigureBoneData::default(),
FigureBoneData::default(), FigureBoneData::default(),
FigureBoneData::default(), FigureBoneData::default(),
FigureBoneData::default(), FigureBoneData::default(),
FigureBoneData::default(), FigureBoneData::default(),
FigureBoneData::default(), FigureBoneData::default(),
FigureBoneData::default(), FigureBoneData::default(),
FigureBoneData::default(), FigureBoneData::default(),
] FigureBoneData::default(),
],
Vec3::default(),
)
} }
fn interpolate(&mut self, target: &Self, dt: f32) { fn interpolate(&mut self, target: &Self, dt: f32) {

View File

@ -1,5 +1,6 @@
use super::Skeleton; use super::Skeleton;
use crate::render::FigureBoneData; use crate::render::FigureBoneData;
use vek::Vec3;
#[derive(Clone)] #[derive(Clone)]
pub struct FixtureSkeleton; pub struct FixtureSkeleton;
@ -15,25 +16,28 @@ impl Skeleton for FixtureSkeleton {
fn bone_count(&self) -> usize { 1 } 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()), FigureBoneData::new(vek::Mat4::identity()), // <-- This is actually a bone!
FigureBoneData::new(vek::Mat4::identity()), FigureBoneData::new(vek::Mat4::identity()),
FigureBoneData::new(vek::Mat4::identity()), FigureBoneData::new(vek::Mat4::identity()),
FigureBoneData::new(vek::Mat4::identity()), FigureBoneData::new(vek::Mat4::identity()),
FigureBoneData::new(vek::Mat4::identity()), FigureBoneData::new(vek::Mat4::identity()),
FigureBoneData::new(vek::Mat4::identity()), FigureBoneData::new(vek::Mat4::identity()),
FigureBoneData::new(vek::Mat4::identity()), FigureBoneData::new(vek::Mat4::identity()),
FigureBoneData::new(vek::Mat4::identity()), FigureBoneData::new(vek::Mat4::identity()),
FigureBoneData::new(vek::Mat4::identity()), FigureBoneData::new(vek::Mat4::identity()),
FigureBoneData::new(vek::Mat4::identity()), FigureBoneData::new(vek::Mat4::identity()),
FigureBoneData::new(vek::Mat4::identity()), FigureBoneData::new(vek::Mat4::identity()),
FigureBoneData::new(vek::Mat4::identity()), FigureBoneData::new(vek::Mat4::identity()),
FigureBoneData::new(vek::Mat4::identity()), FigureBoneData::new(vek::Mat4::identity()),
FigureBoneData::new(vek::Mat4::identity()), FigureBoneData::new(vek::Mat4::identity()),
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) {} fn interpolate(&mut self, _target: &Self, _dt: f32) {}

View File

@ -8,6 +8,7 @@ pub use self::{idle::IdleAnimation, jump::JumpAnimation, run::RunAnimation};
use super::{Bone, Skeleton}; use super::{Bone, Skeleton};
use crate::render::FigureBoneData; use crate::render::FigureBoneData;
use common::comp::{self}; use common::comp::{self};
use vek::Vec3;
#[derive(Clone)] #[derive(Clone)]
pub struct GolemSkeleton { pub struct GolemSkeleton {
@ -45,7 +46,7 @@ impl GolemSkeleton {
impl Skeleton for GolemSkeleton { impl Skeleton for GolemSkeleton {
type Attr = SkeletonAttr; 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 upper_torso_mat = self.upper_torso.compute_base_matrix();
let shoulder_l_mat = self.shoulder_l.compute_base_matrix(); let shoulder_l_mat = self.shoulder_l.compute_base_matrix();
let shoulder_r_mat = self.shoulder_r.compute_base_matrix(); let shoulder_r_mat = self.shoulder_r.compute_base_matrix();
@ -54,24 +55,31 @@ impl Skeleton for GolemSkeleton {
let torso_mat = self.torso.compute_base_matrix(); let torso_mat = self.torso.compute_base_matrix();
let foot_l_mat = self.foot_l.compute_base_matrix(); let foot_l_mat = self.foot_l.compute_base_matrix();
let foot_r_mat = self.foot_r.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 * self.head.compute_base_matrix()),
FigureBoneData::new(torso_mat * upper_torso_mat * shoulder_l_mat), FigureBoneData::new(torso_mat * upper_torso_mat),
FigureBoneData::new(torso_mat * upper_torso_mat * shoulder_r_mat), FigureBoneData::new(torso_mat * upper_torso_mat * shoulder_l_mat),
FigureBoneData::new(torso_mat * upper_torso_mat * self.hand_l.compute_base_matrix()), FigureBoneData::new(torso_mat * upper_torso_mat * shoulder_r_mat),
FigureBoneData::new(torso_mat * upper_torso_mat * self.hand_r.compute_base_matrix()), FigureBoneData::new(
FigureBoneData::new(foot_l_mat * leg_l_mat), torso_mat * upper_torso_mat * self.hand_l.compute_base_matrix(),
FigureBoneData::new(foot_r_mat * leg_r_mat), ),
FigureBoneData::new(foot_l_mat), FigureBoneData::new(
FigureBoneData::new(foot_r_mat), torso_mat * upper_torso_mat * self.hand_r.compute_base_matrix(),
FigureBoneData::default(), ),
FigureBoneData::default(), FigureBoneData::new(foot_l_mat * leg_l_mat),
FigureBoneData::default(), FigureBoneData::new(foot_r_mat * leg_r_mat),
FigureBoneData::default(), FigureBoneData::new(foot_l_mat),
FigureBoneData::default(), FigureBoneData::new(foot_r_mat),
FigureBoneData::default(), FigureBoneData::default(),
] FigureBoneData::default(),
FigureBoneData::default(),
FigureBoneData::default(),
FigureBoneData::default(),
FigureBoneData::default(),
],
Vec3::default(),
)
} }
fn interpolate(&mut self, target: &Self, dt: f32) { fn interpolate(&mut self, target: &Self, dt: f32) {

View File

@ -54,7 +54,7 @@ pub trait Skeleton: Send + Sync + 'static {
fn bone_count(&self) -> usize { 16 } 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`. /// Change the current skeleton to be more like `target`.
fn interpolate(&mut self, target: &Self, dt: f32); fn interpolate(&mut self, target: &Self, dt: f32);

View File

@ -17,25 +17,28 @@ impl Skeleton for ObjectSkeleton {
fn bone_count(&self) -> usize { 1 } 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()), FigureBoneData::new(Mat4::scaling_3d(Vec3::broadcast(SCALE))),
FigureBoneData::new(vek::Mat4::identity()), FigureBoneData::new(vek::Mat4::identity()),
FigureBoneData::new(vek::Mat4::identity()), FigureBoneData::new(vek::Mat4::identity()),
FigureBoneData::new(vek::Mat4::identity()), FigureBoneData::new(vek::Mat4::identity()),
FigureBoneData::new(vek::Mat4::identity()), FigureBoneData::new(vek::Mat4::identity()),
FigureBoneData::new(vek::Mat4::identity()), FigureBoneData::new(vek::Mat4::identity()),
FigureBoneData::new(vek::Mat4::identity()), FigureBoneData::new(vek::Mat4::identity()),
FigureBoneData::new(vek::Mat4::identity()), FigureBoneData::new(vek::Mat4::identity()),
FigureBoneData::new(vek::Mat4::identity()), FigureBoneData::new(vek::Mat4::identity()),
FigureBoneData::new(vek::Mat4::identity()), FigureBoneData::new(vek::Mat4::identity()),
FigureBoneData::new(vek::Mat4::identity()), FigureBoneData::new(vek::Mat4::identity()),
FigureBoneData::new(vek::Mat4::identity()), FigureBoneData::new(vek::Mat4::identity()),
FigureBoneData::new(vek::Mat4::identity()), FigureBoneData::new(vek::Mat4::identity()),
FigureBoneData::new(vek::Mat4::identity()), FigureBoneData::new(vek::Mat4::identity()),
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) {} fn interpolate(&mut self, _target: &Self, _dt: f32) {}

View File

@ -8,6 +8,7 @@ pub use self::{idle::IdleAnimation, jump::JumpAnimation, run::RunAnimation};
use super::{Bone, Skeleton}; use super::{Bone, Skeleton};
use crate::render::FigureBoneData; use crate::render::FigureBoneData;
use common::comp::{self}; use common::comp::{self};
use vek::Vec3;
#[derive(Clone, Default)] #[derive(Clone, Default)]
pub struct QuadrupedMediumSkeleton { pub struct QuadrupedMediumSkeleton {
@ -33,29 +34,32 @@ impl Skeleton for QuadrupedMediumSkeleton {
fn bone_count(&self) -> usize { 11 } 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 ears_mat = self.ears.compute_base_matrix();
let head_upper_mat = self.head_upper.compute_base_matrix(); let head_upper_mat = self.head_upper.compute_base_matrix();
let head_lower_mat = self.head_lower.compute_base_matrix(); let head_lower_mat = self.head_lower.compute_base_matrix();
let torso_mid_mat = self.torso_mid.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), FigureBoneData::new(head_upper_mat),
FigureBoneData::new(head_upper_mat * self.jaw.compute_base_matrix()), FigureBoneData::new(head_upper_mat * head_lower_mat),
FigureBoneData::new(torso_mid_mat * self.tail.compute_base_matrix()), FigureBoneData::new(head_upper_mat * self.jaw.compute_base_matrix()),
FigureBoneData::new(self.torso_back.compute_base_matrix()), FigureBoneData::new(torso_mid_mat * self.tail.compute_base_matrix()),
FigureBoneData::new(torso_mid_mat), FigureBoneData::new(self.torso_back.compute_base_matrix()),
FigureBoneData::new(head_upper_mat * ears_mat), FigureBoneData::new(torso_mid_mat),
FigureBoneData::new(self.foot_lf.compute_base_matrix()), FigureBoneData::new(head_upper_mat * ears_mat),
FigureBoneData::new(self.foot_rf.compute_base_matrix()), FigureBoneData::new(self.foot_lf.compute_base_matrix()),
FigureBoneData::new(self.foot_lb.compute_base_matrix()), FigureBoneData::new(self.foot_rf.compute_base_matrix()),
FigureBoneData::new(self.foot_rb.compute_base_matrix()), FigureBoneData::new(self.foot_lb.compute_base_matrix()),
FigureBoneData::default(), FigureBoneData::new(self.foot_rb.compute_base_matrix()),
FigureBoneData::default(), FigureBoneData::default(),
FigureBoneData::default(), FigureBoneData::default(),
FigureBoneData::default(), FigureBoneData::default(),
FigureBoneData::default(), FigureBoneData::default(),
] FigureBoneData::default(),
],
Vec3::default(),
)
} }
fn interpolate(&mut self, target: &Self, dt: f32) { fn interpolate(&mut self, target: &Self, dt: f32) {

View File

@ -8,6 +8,7 @@ pub use self::{idle::IdleAnimation, jump::JumpAnimation, run::RunAnimation};
use super::{Bone, Skeleton}; use super::{Bone, Skeleton};
use crate::render::FigureBoneData; use crate::render::FigureBoneData;
use common::comp::{self}; use common::comp::{self};
use vek::Vec3;
#[derive(Clone, Default)] #[derive(Clone, Default)]
pub struct QuadrupedSmallSkeleton { pub struct QuadrupedSmallSkeleton {
@ -28,25 +29,28 @@ impl Skeleton for QuadrupedSmallSkeleton {
fn bone_count(&self) -> usize { 6 } 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()), FigureBoneData::new(self.head.compute_base_matrix()),
FigureBoneData::new(self.leg_lf.compute_base_matrix()), FigureBoneData::new(self.chest.compute_base_matrix()),
FigureBoneData::new(self.leg_rf.compute_base_matrix()), FigureBoneData::new(self.leg_lf.compute_base_matrix()),
FigureBoneData::new(self.leg_lb.compute_base_matrix()), FigureBoneData::new(self.leg_rf.compute_base_matrix()),
FigureBoneData::new(self.leg_rb.compute_base_matrix()), FigureBoneData::new(self.leg_lb.compute_base_matrix()),
FigureBoneData::default(), FigureBoneData::new(self.leg_rb.compute_base_matrix()),
FigureBoneData::default(), FigureBoneData::default(),
FigureBoneData::default(), FigureBoneData::default(),
FigureBoneData::default(), FigureBoneData::default(),
FigureBoneData::default(), FigureBoneData::default(),
FigureBoneData::default(), FigureBoneData::default(),
FigureBoneData::default(), FigureBoneData::default(),
FigureBoneData::default(), FigureBoneData::default(),
FigureBoneData::default(), FigureBoneData::default(),
FigureBoneData::default(), FigureBoneData::default(),
] FigureBoneData::default(),
],
Vec3::default(),
)
} }
fn interpolate(&mut self, target: &Self, dt: f32) { fn interpolate(&mut self, target: &Self, dt: f32) {

View File

@ -106,6 +106,9 @@ impl From<&crate::settings::GamepadSettings> for ControllerSettings {
/*map.entry(settings.game_buttons.wall_leap) /*map.entry(settings.game_buttons.wall_leap)
.or_default() .or_default()
.push(GameInput::WallLeap);*/ .push(GameInput::WallLeap);*/
map.entry(settings.game_buttons.toggle_lantern)
.or_default()
.push(GameInput::ToggleLantern);
map.entry(settings.game_buttons.mount) map.entry(settings.game_buttons.mount)
.or_default() .or_default()
.push(GameInput::Mount); .push(GameInput::Mount);

View File

@ -4,7 +4,7 @@ use common::{
comp::item::{ comp::item::{
armor::Armor, armor::Armor,
tool::{Tool, ToolKind}, tool::{Tool, ToolKind},
Consumable, Ingredient, Item, ItemKind, Lantern, Utility, Consumable, Ingredient, Item, ItemKind, Lantern, LanternKind, Utility,
}, },
figure::Segment, figure::Segment,
}; };
@ -20,7 +20,7 @@ use vek::*;
#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)] #[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub enum ItemKey { pub enum ItemKey {
Tool(ToolKind), Tool(ToolKind),
Lantern(Lantern), Lantern(LanternKind),
Armor(Armor), Armor(Armor),
Utility(Utility), Utility(Utility),
Consumable(Consumable), Consumable(Consumable),
@ -31,7 +31,7 @@ impl From<&Item> for ItemKey {
fn from(item: &Item) -> Self { fn from(item: &Item) -> Self {
match &item.kind { match &item.kind {
ItemKind::Tool(Tool { kind, .. }) => ItemKey::Tool(kind.clone()), 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::Armor { kind, .. } => ItemKey::Armor(kind.clone()),
ItemKind::Utility { kind, .. } => ItemKey::Utility(kind.clone()), ItemKind::Utility { kind, .. } => ItemKey::Utility(kind.clone()),
ItemKind::Consumable { kind, .. } => ItemKey::Consumable(kind.clone()), ItemKind::Consumable { kind, .. } => ItemKey::Consumable(kind.clone()),

View File

@ -12,7 +12,7 @@ use common::{
item::{ item::{
armor::{Armor, Back, Belt, Chest, Foot, Hand, Head, Pants, Shoulder, Tabard}, armor::{Armor, Back, Belt, Chest, Foot, Hand, Head, Pants, Shoulder, Tabard},
tool::{Tool, ToolKind}, tool::{Tool, ToolKind},
ItemKind, Lantern, ItemKind, Lantern, LanternKind,
}, },
object, object,
quadruped_medium::{BodyType as QMBodyType, Species as QMSpecies}, quadruped_medium::{BodyType as QMBodyType, Species as QMSpecies},
@ -259,7 +259,7 @@ pub struct HumArmorFootSpec(ArmorVoxSpecMap<Foot, ArmorVoxSpec>);
#[derive(Serialize, Deserialize)] #[derive(Serialize, Deserialize)]
pub struct HumMainWeaponSpec(HashMap<ToolKind, ArmorVoxSpec>); pub struct HumMainWeaponSpec(HashMap<ToolKind, ArmorVoxSpec>);
#[derive(Serialize, Deserialize)] #[derive(Serialize, Deserialize)]
pub struct HumArmorLanternSpec(ArmorVoxSpecMap<Lantern, ArmorVoxSpec>); pub struct HumArmorLanternSpec(ArmorVoxSpecMap<LanternKind, ArmorVoxSpec>);
#[derive(Serialize, Deserialize)] #[derive(Serialize, Deserialize)]
pub struct HumArmorHeadSpec(ArmorVoxSpecMap<Head, ArmorVoxSpec>); pub struct HumArmorHeadSpec(ArmorVoxSpecMap<Head, ArmorVoxSpec>);
#[derive(Serialize, Deserialize)] #[derive(Serialize, Deserialize)]
@ -810,18 +810,19 @@ impl HumArmorLanternSpec {
loadout: &Loadout, loadout: &Loadout,
generate_mesh: impl FnOnce(&Segment, Vec3<f32>) -> Mesh<FigurePipeline>, generate_mesh: impl FnOnce(&Segment, Vec3<f32>) -> Mesh<FigurePipeline>,
) -> Mesh<FigurePipeline> { ) -> Mesh<FigurePipeline> {
let spec = let spec = if let Some(ItemKind::Lantern(Lantern { kind, .. })) =
if let Some(ItemKind::Lantern(lantern)) = loadout.lantern.as_ref().map(|i| &i.kind) { loadout.lantern.as_ref().map(|i| &i.kind)
match self.0.map.get(&lantern) { {
Some(spec) => spec, match self.0.map.get(&kind) {
None => { Some(spec) => spec,
error!("No lantern specification exists for {:?}", lantern); None => {
return load_mesh("not_found", Vec3::new(-4.0, -3.5, 2.0), generate_mesh); error!("No lantern specification exists for {:?}", kind);
}, return load_mesh("not_found", Vec3::new(-4.0, -3.5, 2.0), generate_mesh);
} },
} else { }
&self.0.default } else {
}; &self.0.default
};
let mut lantern_segment = color_segment( let mut lantern_segment = color_segment(
graceful_load_mat_segment(&spec.vox_spec.0), graceful_load_mat_segment(&spec.vox_spec.0),

View File

@ -21,10 +21,10 @@ use crate::{
}; };
use common::{ use common::{
comp::{ comp::{
item::ItemKind, Body, CharacterState, Last, Loadout, Ori, PhysicsState, Pos, Scale, Stats, item::ItemKind, Body, CharacterState, Last, LightAnimation, LightEmitter, Loadout, Ori,
Vel, PhysicsState, Pos, Scale, Stats, Vel,
}, },
state::State, state::{DeltaTime, State},
states::triple_strike, states::triple_strike,
terrain::TerrainChunk, terrain::TerrainChunk,
vol::RectRasterableVol, vol::RectRasterableVol,
@ -108,6 +108,61 @@ impl FigureMgr {
self.golem_model_cache.clean(tick); 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) { pub fn maintain(&mut self, renderer: &mut Renderer, scene_data: &SceneData, camera: &Camera) {
let state = scene_data.state; let state = scene_data.state;
let time = state.get_time(); 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. // Clear states that have deleted entities.
self.character_states self.character_states
.retain(|entity, _| ecs.entities().is_alive(*entity)); .retain(|entity, _| ecs.entities().is_alive(*entity));
@ -1932,6 +1990,7 @@ impl FigureMgr {
pub struct FigureState<S: Skeleton> { pub struct FigureState<S: Skeleton> {
bone_consts: Consts<FigureBoneData>, bone_consts: Consts<FigureBoneData>,
locals: Consts<FigureLocals>, locals: Consts<FigureLocals>,
lantern_offset: Vec3<f32>,
state_time: f64, state_time: f64,
skeleton: S, skeleton: S,
last_ori: Vec3<f32>, last_ori: Vec3<f32>,
@ -1941,11 +2000,11 @@ pub struct FigureState<S: Skeleton> {
impl<S: Skeleton> FigureState<S> { impl<S: Skeleton> FigureState<S> {
pub fn new(renderer: &mut Renderer, skeleton: S) -> Self { pub fn new(renderer: &mut Renderer, skeleton: S) -> Self {
let (bone_consts, lantern_offset) = skeleton.compute_matrices();
Self { Self {
bone_consts: renderer bone_consts: renderer.create_consts(&bone_consts).unwrap(),
.create_consts(&skeleton.compute_matrices())
.unwrap(),
locals: renderer.create_consts(&[FigureLocals::default()]).unwrap(), locals: renderer.create_consts(&[FigureLocals::default()]).unwrap(),
lantern_offset,
state_time: 0.0, state_time: 0.0,
skeleton, skeleton,
last_ori: Vec3::zero(), last_ori: Vec3::zero(),
@ -1984,12 +2043,14 @@ impl<S: Skeleton> FigureState<S> {
let locals = FigureLocals::new(mat, col, is_player); let locals = FigureLocals::new(mat, col, is_player);
renderer.update_consts(&mut self.locals, &[locals]).unwrap(); renderer.update_consts(&mut self.locals, &[locals]).unwrap();
let (new_bone_consts, lantern_offset) = self.skeleton.compute_matrices();
renderer renderer
.update_consts( .update_consts(
&mut self.bone_consts, &mut self.bone_consts,
&self.skeleton.compute_matrices()[0..self.skeleton.bone_count()], &new_bone_consts[0..self.skeleton.bone_count()],
) )
.unwrap(); .unwrap();
self.lantern_offset = lantern_offset;
} }
pub fn locals(&self) -> &Consts<FigureLocals> { &self.locals } pub fn locals(&self) -> &Consts<FigureLocals> { &self.locals }

View File

@ -270,14 +270,17 @@ impl Scene {
.ecs() .ecs()
.read_storage::<crate::ecs::comp::Interpolated>() .read_storage::<crate::ecs::comp::Interpolated>()
.maybe(), .maybe(),
&scene_data.state.ecs().read_storage::<comp::LightEmitter>(), &scene_data
.state
.ecs()
.read_storage::<comp::LightAnimation>(),
) )
.join() .join()
.filter(|(pos, _, _, _)| { .filter(|(pos, _, _, _)| {
(pos.0.distance_squared(player_pos) as f32) (pos.0.distance_squared(player_pos) as f32)
< self.loaded_distance.powf(2.0) + LIGHT_DIST_RADIUS < 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 // Use interpolated values if they are available
let (pos, ori) = let (pos, ori) =
interpolated.map_or((pos.0, ori.map(|o| o.0)), |i| (i.pos, Some(i.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( Light::new(
pos + (rot * light_emitter.offset), pos + (rot * light_anim.offset),
light_emitter.col, light_anim.col,
light_emitter.strength, light_anim.strength,
) )
}) })
.collect::<Vec<_>>(); .collect::<Vec<_>>();

View File

@ -331,6 +331,9 @@ impl PlayState for SessionState {
self.client.borrow_mut().swap_loadout(); self.client.borrow_mut().swap_loadout();
} }
} }
Event::InputUpdate(GameInput::ToggleLantern, true) => {
self.client.borrow_mut().toggle_lantern();
},
Event::InputUpdate(GameInput::Mount, true) => { Event::InputUpdate(GameInput::Mount, true) => {
let mut client = self.client.borrow_mut(); let mut client = self.client.borrow_mut();
if client.is_mounted() { if client.is_mounted() {

View File

@ -120,6 +120,7 @@ impl ControlSettings {
GameInput::Climb => KeyMouse::Key(VirtualKeyCode::Space), GameInput::Climb => KeyMouse::Key(VirtualKeyCode::Space),
GameInput::ClimbDown => KeyMouse::Key(VirtualKeyCode::LControl), GameInput::ClimbDown => KeyMouse::Key(VirtualKeyCode::LControl),
//GameInput::WallLeap => MIDDLE_CLICK_KEY, //GameInput::WallLeap => MIDDLE_CLICK_KEY,
GameInput::ToggleLantern => KeyMouse::Key(VirtualKeyCode::G),
GameInput::Mount => KeyMouse::Key(VirtualKeyCode::F), GameInput::Mount => KeyMouse::Key(VirtualKeyCode::F),
GameInput::Map => KeyMouse::Key(VirtualKeyCode::M), GameInput::Map => KeyMouse::Key(VirtualKeyCode::M),
GameInput::Bag => KeyMouse::Key(VirtualKeyCode::B), GameInput::Bag => KeyMouse::Key(VirtualKeyCode::B),
@ -175,6 +176,7 @@ impl Default for ControlSettings {
GameInput::Climb, GameInput::Climb,
GameInput::ClimbDown, GameInput::ClimbDown,
//GameInput::WallLeap, //GameInput::WallLeap,
GameInput::ToggleLantern,
GameInput::Mount, GameInput::Mount,
GameInput::Enter, GameInput::Enter,
GameInput::Command, GameInput::Command,
@ -275,6 +277,7 @@ pub mod con_settings {
pub climb: Button, pub climb: Button,
pub climb_down: Button, pub climb_down: Button,
//pub wall_leap: Button, //pub wall_leap: Button,
pub toggle_lantern: Button,
pub mount: Button, pub mount: Button,
pub map: Button, pub map: Button,
pub bag: Button, pub bag: Button,
@ -361,6 +364,7 @@ pub mod con_settings {
climb: Button::Simple(GilButton::South), climb: Button::Simple(GilButton::South),
climb_down: Button::Simple(GilButton::Unknown), climb_down: Button::Simple(GilButton::Unknown),
//wall_leap: Button::Simple(GilButton::Unknown), //wall_leap: Button::Simple(GilButton::Unknown),
toggle_lantern: Button::Simple(GilButton::East),
mount: Button::Simple(GilButton::North), mount: Button::Simple(GilButton::North),
map: Button::Simple(GilButton::DPadRight), map: Button::Simple(GilButton::DPadRight),
bag: Button::Simple(GilButton::DPadDown), bag: Button::Simple(GilButton::DPadDown),

View File

@ -38,6 +38,7 @@ pub enum GameInput {
Climb, Climb,
ClimbDown, ClimbDown,
//WallLeap, //WallLeap,
ToggleLantern,
Mount, Mount,
Enter, Enter,
Command, Command,
@ -78,6 +79,7 @@ impl GameInput {
GameInput::Climb => "gameinput.climb", GameInput::Climb => "gameinput.climb",
GameInput::ClimbDown => "gameinput.climbdown", GameInput::ClimbDown => "gameinput.climbdown",
//GameInput::WallLeap => "gameinput.wallleap", //GameInput::WallLeap => "gameinput.wallleap",
GameInput::ToggleLantern => "gameinput.togglelantern",
GameInput::Mount => "gameinput.mount", GameInput::Mount => "gameinput.mount",
GameInput::Enter => "gameinput.enter", GameInput::Enter => "gameinput.enter",
GameInput::Command => "gameinput.command", GameInput::Command => "gameinput.command",