Add loadout struct for info on weapon configurations

This commit is contained in:
timokoesters 2020-03-14 22:33:20 +01:00
parent 7dfe00b674
commit 598a4c6cbb
23 changed files with 263 additions and 213 deletions

View File

@ -1,5 +1,5 @@
use crate::{ use crate::{
comp::{CharacterState, ToolData}, comp::{CharacterState, Item, ToolData},
states::*, states::*,
}; };
use specs::{Component, DenseVecStorage, FlaggedStorage, HashMapStorage}; use specs::{Component, DenseVecStorage, FlaggedStorage, HashMapStorage};
@ -25,12 +25,20 @@ impl Component for CharacterAbility {
type Storage = DenseVecStorage<Self>; type Storage = DenseVecStorage<Self>;
} }
#[derive(Copy, Clone, Default, Debug, Serialize, Deserialize)] #[derive(Clone, Debug, Serialize, Deserialize)]
pub struct AbilityPool { pub struct ItemConfig {
pub primary: Option<CharacterAbility>, pub item: Item,
pub secondary: Option<CharacterAbility>, pub primary_ability: Option<CharacterAbility>,
pub block: Option<CharacterAbility>, pub secondary_ability: Option<CharacterAbility>,
pub dodge: Option<CharacterAbility>, pub block_ability: Option<CharacterAbility>,
pub dodge_ability: Option<CharacterAbility>,
}
#[derive(Clone, Default, Debug, Serialize, Deserialize)]
pub struct Loadout {
pub active_item: Option<ItemConfig>,
pub second_item: Option<ItemConfig>,
// armor
} }
impl From<CharacterAbility> for CharacterState { impl From<CharacterAbility> for CharacterState {
@ -69,6 +77,6 @@ impl From<CharacterAbility> for CharacterState {
} }
} }
impl Component for AbilityPool { impl Component for Loadout {
type Storage = FlaggedStorage<Self, HashMapStorage<Self>>; type Storage = FlaggedStorage<Self, HashMapStorage<Self>>;
} }

View File

@ -95,7 +95,7 @@ impl Component for CharacterState {
#[derive(Copy, Clone, Debug, PartialEq, Serialize, Deserialize, Eq, Hash)] #[derive(Copy, Clone, Debug, PartialEq, Serialize, Deserialize, Eq, Hash)]
pub struct Attacking { pub struct Attacking {
pub weapon: Option<ToolData>, pub base_damage: u32,
pub applied: bool, pub applied: bool,
pub hit_count: u32, pub hit_count: u32,
} }

View File

@ -127,8 +127,8 @@ pub struct ToolData {
equip_time_millis: u64, equip_time_millis: u64,
attack_buildup_millis: u64, attack_buildup_millis: u64,
attack_recover_millis: u64, attack_recover_millis: u64,
range: u64, range: u32,
pub base_damage: u64, pub base_damage: u32,
} }
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)] #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]

View File

@ -16,7 +16,7 @@ mod stats;
mod visual; mod visual;
// Reexports // Reexports
pub use ability::{AbilityPool, CharacterAbility}; pub use ability::{CharacterAbility, ItemConfig, Loadout};
pub use admin::Admin; pub use admin::Admin;
pub use agent::{Agent, Alignment}; pub use agent::{Agent, Alignment};
pub use body::{ pub use body::{
@ -39,5 +39,5 @@ pub use location::{Waypoint, WaypointArea};
pub use phys::{ForceUpdate, Gravity, Mass, Ori, PhysicsState, Pos, Scale, Sticky, Vel}; pub use phys::{ForceUpdate, Gravity, Mass, Ori, PhysicsState, Pos, Scale, Sticky, Vel};
pub use player::Player; pub use player::Player;
pub use projectile::Projectile; pub use projectile::Projectile;
pub use stats::{Equipment, Exp, HealthChange, HealthSource, Level, Stats}; pub use stats::{Exp, HealthChange, HealthSource, Level, Stats};
pub use visual::LightEmitter; pub use visual::LightEmitter;

View File

@ -42,13 +42,6 @@ pub struct Level {
amount: u32, amount: u32,
} }
#[derive(Clone, PartialEq, Eq, Hash, Debug, Serialize, Deserialize)]
pub struct Equipment {
pub main: Option<comp::Item>,
pub alt: Option<comp::Item>,
// TODO: Armor
}
impl Health { impl Health {
pub fn current(&self) -> u32 { self.current } pub fn current(&self) -> u32 { self.current }
@ -125,7 +118,6 @@ pub struct Stats {
pub health: Health, pub health: Health,
pub level: Level, pub level: Level,
pub exp: Exp, pub exp: Exp,
pub equipment: Equipment,
pub endurance: u32, pub endurance: u32,
pub fitness: u32, pub fitness: u32,
pub willpower: u32, pub willpower: u32,
@ -178,7 +170,6 @@ impl Stats {
current: 0, current: 0,
maximum: 50, maximum: 50,
}, },
equipment: Equipment { main, alt: None },
endurance, endurance,
fitness, fitness,
willpower, willpower,

View File

@ -22,7 +22,7 @@ sum_type! {
Gravity(comp::Gravity), Gravity(comp::Gravity),
Sticky(comp::Sticky), Sticky(comp::Sticky),
CharacterAbility(comp::CharacterAbility), CharacterAbility(comp::CharacterAbility),
AbilityPool(comp::AbilityPool), Loadout(comp::Loadout),
Attacking(comp::Attacking), Attacking(comp::Attacking),
CharacterState(comp::CharacterState), CharacterState(comp::CharacterState),
} }
@ -46,7 +46,7 @@ sum_type! {
Gravity(PhantomData<comp::Gravity>), Gravity(PhantomData<comp::Gravity>),
Sticky(PhantomData<comp::Sticky>), Sticky(PhantomData<comp::Sticky>),
CharacterAbility(PhantomData<comp::CharacterAbility>), CharacterAbility(PhantomData<comp::CharacterAbility>),
AbilityPool(PhantomData<comp::AbilityPool>), Loadout(PhantomData<comp::Loadout>),
Attacking(PhantomData<comp::Attacking>), Attacking(PhantomData<comp::Attacking>),
CharacterState(PhantomData<comp::CharacterState>), CharacterState(PhantomData<comp::CharacterState>),
} }
@ -70,7 +70,7 @@ impl sync::CompPacket for EcsCompPacket {
EcsCompPacket::Gravity(comp) => sync::handle_insert(comp, entity, world), EcsCompPacket::Gravity(comp) => sync::handle_insert(comp, entity, world),
EcsCompPacket::Sticky(comp) => sync::handle_insert(comp, entity, world), EcsCompPacket::Sticky(comp) => sync::handle_insert(comp, entity, world),
EcsCompPacket::CharacterAbility(comp) => sync::handle_insert(comp, entity, world), EcsCompPacket::CharacterAbility(comp) => sync::handle_insert(comp, entity, world),
EcsCompPacket::AbilityPool(comp) => sync::handle_insert(comp, entity, world), EcsCompPacket::Loadout(comp) => sync::handle_insert(comp, entity, world),
EcsCompPacket::Attacking(comp) => sync::handle_insert(comp, entity, world), EcsCompPacket::Attacking(comp) => sync::handle_insert(comp, entity, world),
EcsCompPacket::CharacterState(comp) => sync::handle_insert(comp, entity, world), EcsCompPacket::CharacterState(comp) => sync::handle_insert(comp, entity, world),
} }
@ -92,7 +92,7 @@ impl sync::CompPacket for EcsCompPacket {
EcsCompPacket::Gravity(comp) => sync::handle_modify(comp, entity, world), EcsCompPacket::Gravity(comp) => sync::handle_modify(comp, entity, world),
EcsCompPacket::Sticky(comp) => sync::handle_modify(comp, entity, world), EcsCompPacket::Sticky(comp) => sync::handle_modify(comp, entity, world),
EcsCompPacket::CharacterAbility(comp) => sync::handle_modify(comp, entity, world), EcsCompPacket::CharacterAbility(comp) => sync::handle_modify(comp, entity, world),
EcsCompPacket::AbilityPool(comp) => sync::handle_modify(comp, entity, world), EcsCompPacket::Loadout(comp) => sync::handle_modify(comp, entity, world),
EcsCompPacket::Attacking(comp) => sync::handle_modify(comp, entity, world), EcsCompPacket::Attacking(comp) => sync::handle_modify(comp, entity, world),
EcsCompPacket::CharacterState(comp) => sync::handle_modify(comp, entity, world), EcsCompPacket::CharacterState(comp) => sync::handle_modify(comp, entity, world),
} }
@ -118,9 +118,7 @@ impl sync::CompPacket for EcsCompPacket {
EcsCompPhantom::CharacterAbility(_) => { EcsCompPhantom::CharacterAbility(_) => {
sync::handle_remove::<comp::CharacterAbility>(entity, world) sync::handle_remove::<comp::CharacterAbility>(entity, world)
}, },
EcsCompPhantom::AbilityPool(_) => { EcsCompPhantom::Loadout(_) => sync::handle_remove::<comp::Loadout>(entity, world),
sync::handle_remove::<comp::AbilityPool>(entity, world)
},
EcsCompPhantom::Attacking(_) => sync::handle_remove::<comp::Attacking>(entity, world), EcsCompPhantom::Attacking(_) => sync::handle_remove::<comp::Attacking>(entity, world),
EcsCompPhantom::CharacterState(_) => { EcsCompPhantom::CharacterState(_) => {
sync::handle_remove::<comp::CharacterState>(entity, world) sync::handle_remove::<comp::CharacterState>(entity, world)

View File

@ -106,7 +106,7 @@ impl State {
// Uids for sync // Uids for sync
ecs.register_sync_marker(); ecs.register_sync_marker();
// Register server -> all clients synced components. // Register server -> all clients synced components.
ecs.register::<comp::AbilityPool>(); ecs.register::<comp::Loadout>();
ecs.register::<comp::CharacterAbility>(); ecs.register::<comp::CharacterAbility>();
ecs.register::<comp::Projectile>(); ecs.register::<comp::Projectile>();
ecs.register::<comp::Body>(); ecs.register::<comp::Body>();

View File

@ -29,9 +29,8 @@ impl CharacterBehavior for Data {
handle_move(data, &mut update); handle_move(data, &mut update);
// Build up window // Build up
if self.buildup_duration != Duration::default() { if self.buildup_duration != Duration::default() {
// Start to swing
update.character = CharacterState::BasicAttack(Data { update.character = CharacterState::BasicAttack(Data {
buildup_duration: self buildup_duration: self
.buildup_duration .buildup_duration
@ -41,12 +40,11 @@ impl CharacterBehavior for Data {
exhausted: false, exhausted: false,
}); });
} }
// Hit attempt window // Hit attempt
else if !self.exhausted { else if !self.exhausted {
// Swing hits
if let Some(tool) = unwrap_tool_data(data) { if let Some(tool) = unwrap_tool_data(data) {
data.updater.insert(data.entity, Attacking { data.updater.insert(data.entity, Attacking {
weapon: Some(tool), base_damage: tool.base_damage,
applied: false, applied: false,
hit_count: 0, hit_count: 0,
}); });
@ -58,7 +56,7 @@ impl CharacterBehavior for Data {
exhausted: true, exhausted: true,
}); });
} }
// Swing recovery window // Recovery
else if self.recover_duration != Duration::default() { else if self.recover_duration != Duration::default() {
update.character = CharacterState::BasicAttack(Data { update.character = CharacterState::BasicAttack(Data {
buildup_duration: self.buildup_duration, buildup_duration: self.buildup_duration,
@ -79,7 +77,8 @@ impl CharacterBehavior for Data {
update.character = CharacterState::Idle; update.character = CharacterState::Idle;
} }
} }
// Subtract energy on successful hit
// Grant energy on successful hit
if let Some(attack) = data.attacking { if let Some(attack) = data.attacking {
if attack.applied && attack.hit_count > 0 { if attack.applied && attack.hit_count > 0 {
data.updater.remove::<Attacking>(data.entity); data.updater.remove::<Attacking>(data.entity);

View File

@ -62,7 +62,7 @@ impl CharacterBehavior for Data {
else if !self.stage_exhausted { else if !self.stage_exhausted {
// Swing hits // Swing hits
data.updater.insert(data.entity, Attacking { data.updater.insert(data.entity, Attacking {
weapon: Some(self.tool), base_damage: self.tool.base_damage,
applied: false, applied: false,
hit_count: 0, hit_count: 0,
}); });

View File

@ -119,7 +119,7 @@ pub fn handle_wield(data: &JoinData, update: &mut StateUpdate) {
/// If a tool is equipped, goes into Equipping state, otherwise goes to Idle /// If a tool is equipped, goes into Equipping state, otherwise goes to Idle
pub fn attempt_wield(data: &JoinData, update: &mut StateUpdate) { pub fn attempt_wield(data: &JoinData, update: &mut StateUpdate) {
if let Some(Tool(tool)) = data.stats.equipment.main.as_ref().map(|i| i.kind) { if let Some(Tool(tool)) = data.loadout.active_item.as_ref().map(|i| i.item.kind) {
update.character = CharacterState::Equipping(equipping::Data { update.character = CharacterState::Equipping(equipping::Data {
tool, tool,
time_left: tool.equip_time(), time_left: tool.equip_time(),
@ -192,7 +192,12 @@ pub fn handle_primary_input(data: &JoinData, update: &mut StateUpdate) {
/// Attempts to go into `ability_pool.primary` if is `Some()` on `AbilityPool` /// Attempts to go into `ability_pool.primary` if is `Some()` on `AbilityPool`
pub fn attempt_primary_ability(data: &JoinData, update: &mut StateUpdate) { pub fn attempt_primary_ability(data: &JoinData, update: &mut StateUpdate) {
if let Some(ability) = data.ability_pool.primary { if let Some(ability) = data
.loadout
.active_item
.as_ref()
.and_then(|i| i.primary_ability)
{
update.character = ability.into(); update.character = ability.into();
} }
} }
@ -209,7 +214,12 @@ pub fn handle_secondary_input(data: &JoinData, update: &mut StateUpdate) {
/// Attempts to go into `ability_pool.secondary` if is `Some()` on `AbilityPool` /// Attempts to go into `ability_pool.secondary` if is `Some()` on `AbilityPool`
pub fn attempt_secondary_ability(data: &JoinData, update: &mut StateUpdate) { pub fn attempt_secondary_ability(data: &JoinData, update: &mut StateUpdate) {
if let Some(ability) = data.ability_pool.secondary { if let Some(ability) = data
.loadout
.active_item
.as_ref()
.and_then(|i| i.secondary_ability)
{
update.character = ability.into(); update.character = ability.into();
} }
} }
@ -233,13 +243,18 @@ pub fn handle_dodge_input(data: &JoinData, update: &mut StateUpdate) {
} }
pub fn attempt_dodge_ability(data: &JoinData, update: &mut StateUpdate) { pub fn attempt_dodge_ability(data: &JoinData, update: &mut StateUpdate) {
if let Some(ability) = data.ability_pool.dodge { if let Some(ability) = data
.loadout
.active_item
.as_ref()
.and_then(|i| i.dodge_ability)
{
update.character = ability.into(); update.character = ability.into();
} }
} }
pub fn unwrap_tool_data(data: &JoinData) -> Option<ToolData> { pub fn unwrap_tool_data(data: &JoinData) -> Option<ToolData> {
if let Some(Tool(tool)) = data.stats.equipment.main.as_ref().map(|i| i.kind) { if let Some(Tool(tool)) = data.loadout.active_item.as_ref().map(|i| i.item.kind) {
Some(tool) Some(tool)
} else { } else {
None None

View File

@ -1,7 +1,7 @@
use crate::{ use crate::{
comp::{ comp::{
AbilityPool, Attacking, Body, CharacterState, Controller, ControllerInputs, Energy, Attacking, Body, CharacterState, Controller, ControllerInputs, Energy, Loadout, Mounting,
Mounting, Ori, PhysicsState, Pos, StateUpdate, Stats, Vel, Ori, PhysicsState, Pos, StateUpdate, Stats, Vel,
}, },
event::{EventBus, LocalEvent, ServerEvent}, event::{EventBus, LocalEvent, ServerEvent},
state::DeltaTime, state::DeltaTime,
@ -33,7 +33,7 @@ pub struct JoinData<'a> {
pub energy: &'a Energy, pub energy: &'a Energy,
pub body: &'a Body, pub body: &'a Body,
pub physics: &'a PhysicsState, pub physics: &'a PhysicsState,
pub ability_pool: &'a AbilityPool, pub loadout: &'a Loadout,
pub attacking: Option<&'a Attacking>, pub attacking: Option<&'a Attacking>,
pub updater: &'a LazyUpdate, pub updater: &'a LazyUpdate,
} }
@ -50,7 +50,7 @@ pub type JoinTuple<'a> = (
&'a Stats, &'a Stats,
&'a Body, &'a Body,
&'a PhysicsState, &'a PhysicsState,
&'a AbilityPool, &'a Loadout,
Option<&'a Attacking>, Option<&'a Attacking>,
); );
@ -69,7 +69,7 @@ impl<'a> JoinData<'a> {
stats: j.8, stats: j.8,
body: j.9, body: j.9,
physics: j.10, physics: j.10,
ability_pool: j.11, loadout: j.11,
attacking: j.12, attacking: j.12,
updater, updater,
dt, dt,
@ -102,7 +102,7 @@ impl<'a> System<'a> for Sys {
ReadStorage<'a, Stats>, ReadStorage<'a, Stats>,
ReadStorage<'a, Body>, ReadStorage<'a, Body>,
ReadStorage<'a, PhysicsState>, ReadStorage<'a, PhysicsState>,
ReadStorage<'a, AbilityPool>, ReadStorage<'a, Loadout>,
ReadStorage<'a, Attacking>, ReadStorage<'a, Attacking>,
ReadStorage<'a, Uid>, ReadStorage<'a, Uid>,
ReadStorage<'a, Mounting>, ReadStorage<'a, Mounting>,
@ -126,7 +126,7 @@ impl<'a> System<'a> for Sys {
stats, stats,
bodies, bodies,
physics_states, physics_states,
ability_pools, loadouts,
attacking_storage, attacking_storage,
uids, uids,
mountings, mountings,
@ -144,7 +144,7 @@ impl<'a> System<'a> for Sys {
&stats, &stats,
&bodies, &bodies,
&physics_states, &physics_states,
&ability_pools, &loadouts,
attacking_storage.maybe(), attacking_storage.maybe(),
) )
.join(); .join();

View File

@ -104,19 +104,19 @@ impl<'a> System<'a> for Sys {
&& ori2.angle_between(pos_b2 - pos2) < ATTACK_ANGLE.to_radians() / 2.0 + (rad_b / pos2.distance(pos_b2)).atan() && ori2.angle_between(pos_b2 - pos2) < ATTACK_ANGLE.to_radians() / 2.0 + (rad_b / pos2.distance(pos_b2)).atan()
{ {
// Weapon gives base damage // Weapon gives base damage
let mut dmg = attack.weapon.map(|w| w.base_damage as i32).unwrap_or(3); let mut dmg = attack.base_damage;
// Block // Block
if character_b.is_block() if character_b.is_block()
&& ori_b.0.angle_between(pos.0 - pos_b.0) < BLOCK_ANGLE.to_radians() / 2.0 && ori_b.0.angle_between(pos.0 - pos_b.0) < BLOCK_ANGLE.to_radians() / 2.0
{ {
dmg = (dmg as f32 * (1.0 - BLOCK_EFFICIENCY)) as i32 dmg = (dmg as f32 * (1.0 - BLOCK_EFFICIENCY)) as u32
} }
server_bus.emitter().emit(ServerEvent::Damage { server_bus.emitter().emit(ServerEvent::Damage {
uid: *uid_b, uid: *uid_b,
change: HealthChange { change: HealthChange {
amount: -dmg, amount: -(dmg as i32),
cause: HealthSource::Attack { by: *uid }, cause: HealthSource::Attack { by: *uid },
}, },
}); });

View File

@ -83,22 +83,6 @@ pub fn handle_inventory(server: &mut Server, entity: EcsEntity, manip: comp::Inv
if let Some(item) = item_opt { if let Some(item) = item_opt {
match item.kind { match item.kind {
comp::ItemKind::Tool { .. } => {
if let Some(stats) =
state.ecs().write_storage::<comp::Stats>().get_mut(entity)
{
// Insert old item into inventory
if let Some(old_item) = stats.equipment.main.take() {
state
.ecs()
.write_storage::<comp::Inventory>()
.get_mut(entity)
.map(|inv| inv.insert(slot, old_item));
}
stats.equipment.main = Some(item);
}
},
comp::ItemKind::Consumable { kind, effect } => { comp::ItemKind::Consumable { kind, effect } => {
event = comp::InventoryUpdateEvent::Consumed(kind); event = comp::InventoryUpdateEvent::Consumed(kind);
state.apply_effect(entity, effect); state.apply_effect(entity, effect);

View File

@ -289,21 +289,21 @@ impl Server {
state.write_component( state.write_component(
entity, entity,
if let Some(comp::Item { if let Some(comp::ItemKind::Tool(tool)) = main.as_ref().map(|i| i.kind) {
kind: comp::ItemKind::Tool(tool),
..
}) = main
{
let mut abilities = tool.get_abilities(); let mut abilities = tool.get_abilities();
let mut ability_drain = abilities.drain(..); let mut ability_drain = abilities.drain(..);
comp::AbilityPool { comp::Loadout {
primary: ability_drain.next(), active_item: main.map(|item| comp::ItemConfig {
secondary: ability_drain.next(), item,
block: Some(comp::CharacterAbility::BasicBlock), primary_ability: ability_drain.next(),
dodge: Some(comp::CharacterAbility::Roll), secondary_ability: ability_drain.next(),
block_ability: Some(comp::CharacterAbility::BasicBlock),
dodge_ability: Some(comp::CharacterAbility::Roll),
}),
second_item: None,
} }
} else { } else {
comp::AbilityPool::default() comp::Loadout::default()
}, },
); );
@ -676,7 +676,7 @@ impl StateExt for State {
.with(comp::Energy::new(500)) .with(comp::Energy::new(500))
.with(comp::Gravity(1.0)) .with(comp::Gravity(1.0))
.with(comp::CharacterState::default()) .with(comp::CharacterState::default())
.with(comp::AbilityPool::default()) .with(comp::Loadout::default()) // TODO Give the poor npc something to do
} }
fn notify_registered_clients(&self, msg: ServerMsg) { fn notify_registered_clients(&self, msg: ServerMsg) {

View File

@ -1,7 +1,7 @@
use super::SysTimer; use super::SysTimer;
use common::{ use common::{
comp::{ comp::{
AbilityPool, Body, CanBuild, CharacterState, Energy, Gravity, Item, LightEmitter, Mass, Body, CanBuild, CharacterState, Energy, Gravity, Item, LightEmitter, Loadout, Mass,
MountState, Mounting, Player, Scale, Stats, Sticky, MountState, Mounting, Player, Scale, Stats, Sticky,
}, },
msg::EcsCompPacket, msg::EcsCompPacket,
@ -51,7 +51,7 @@ pub struct TrackedComps<'a> {
pub mass: ReadStorage<'a, Mass>, pub mass: ReadStorage<'a, Mass>,
pub sticky: ReadStorage<'a, Sticky>, pub sticky: ReadStorage<'a, Sticky>,
pub gravity: ReadStorage<'a, Gravity>, pub gravity: ReadStorage<'a, Gravity>,
pub ability_pool: ReadStorage<'a, AbilityPool>, pub loadout: ReadStorage<'a, Loadout>,
pub character_state: ReadStorage<'a, CharacterState>, pub character_state: ReadStorage<'a, CharacterState>,
} }
impl<'a> TrackedComps<'a> { impl<'a> TrackedComps<'a> {
@ -106,9 +106,9 @@ impl<'a> TrackedComps<'a> {
.get(entity) .get(entity)
.copied() .copied()
.map(|c| comps.push(c.into())); .map(|c| comps.push(c.into()));
self.ability_pool self.loadout
.get(entity) .get(entity)
.copied() .cloned()
.map(|c| comps.push(c.into())); .map(|c| comps.push(c.into()));
self.character_state self.character_state
.get(entity) .get(entity)
@ -134,7 +134,7 @@ pub struct ReadTrackers<'a> {
pub mass: ReadExpect<'a, UpdateTracker<Mass>>, pub mass: ReadExpect<'a, UpdateTracker<Mass>>,
pub sticky: ReadExpect<'a, UpdateTracker<Sticky>>, pub sticky: ReadExpect<'a, UpdateTracker<Sticky>>,
pub gravity: ReadExpect<'a, UpdateTracker<Gravity>>, pub gravity: ReadExpect<'a, UpdateTracker<Gravity>>,
pub ability_pool: ReadExpect<'a, UpdateTracker<AbilityPool>>, pub loadout: ReadExpect<'a, UpdateTracker<Loadout>>,
pub character_state: ReadExpect<'a, UpdateTracker<CharacterState>>, pub character_state: ReadExpect<'a, UpdateTracker<CharacterState>>,
} }
impl<'a> ReadTrackers<'a> { impl<'a> ReadTrackers<'a> {
@ -163,7 +163,7 @@ impl<'a> ReadTrackers<'a> {
.with_component(&comps.uid, &*self.mass, &comps.mass, filter) .with_component(&comps.uid, &*self.mass, &comps.mass, filter)
.with_component(&comps.uid, &*self.sticky, &comps.sticky, filter) .with_component(&comps.uid, &*self.sticky, &comps.sticky, filter)
.with_component(&comps.uid, &*self.gravity, &comps.gravity, filter) .with_component(&comps.uid, &*self.gravity, &comps.gravity, filter)
.with_component(&comps.uid, &*self.ability_pool, &comps.ability_pool, filter) .with_component(&comps.uid, &*self.loadout, &comps.loadout, filter)
.with_component( .with_component(
&comps.uid, &comps.uid,
&*self.character_state, &*self.character_state,
@ -189,7 +189,7 @@ pub struct WriteTrackers<'a> {
mass: WriteExpect<'a, UpdateTracker<Mass>>, mass: WriteExpect<'a, UpdateTracker<Mass>>,
sticky: WriteExpect<'a, UpdateTracker<Sticky>>, sticky: WriteExpect<'a, UpdateTracker<Sticky>>,
gravity: WriteExpect<'a, UpdateTracker<Gravity>>, gravity: WriteExpect<'a, UpdateTracker<Gravity>>,
ability_pool: WriteExpect<'a, UpdateTracker<AbilityPool>>, loadout: WriteExpect<'a, UpdateTracker<Loadout>>,
character_state: WriteExpect<'a, UpdateTracker<CharacterState>>, character_state: WriteExpect<'a, UpdateTracker<CharacterState>>,
} }
@ -209,7 +209,7 @@ fn record_changes(comps: &TrackedComps, trackers: &mut WriteTrackers) {
trackers.mass.record_changes(&comps.mass); trackers.mass.record_changes(&comps.mass);
trackers.sticky.record_changes(&comps.sticky); trackers.sticky.record_changes(&comps.sticky);
trackers.gravity.record_changes(&comps.gravity); trackers.gravity.record_changes(&comps.gravity);
trackers.ability_pool.record_changes(&comps.ability_pool); trackers.loadout.record_changes(&comps.loadout);
trackers trackers
.character_state .character_state
.record_changes(&comps.character_state); .record_changes(&comps.character_state);
@ -230,7 +230,7 @@ pub fn register_trackers(world: &mut World) {
world.register_tracker::<Mass>(); world.register_tracker::<Mass>();
world.register_tracker::<Sticky>(); world.register_tracker::<Sticky>();
world.register_tracker::<Gravity>(); world.register_tracker::<Gravity>();
world.register_tracker::<AbilityPool>(); world.register_tracker::<Loadout>();
world.register_tracker::<CharacterState>(); world.register_tracker::<CharacterState>();
} }

View File

@ -180,7 +180,17 @@ impl<'a> System<'a> for Sys {
.choose(&mut rand::thread_rng()) .choose(&mut rand::thread_rng())
.expect("SPAWN_NPCS is nonempty")( .expect("SPAWN_NPCS is nonempty")(
); );
let mut stats = comp::Stats::new(name, body, main); let mut stats = comp::Stats::new(name, body, main.clone());
let mut loadout = comp::Loadout {
active_item: main.map(|item| comp::ItemConfig {
item,
primary_ability: None,
secondary_ability: None,
block_ability: None,
dodge_ability: None,
}),
second_item: None,
};
let mut scale = 1.0; let mut scale = 1.0;
@ -202,6 +212,17 @@ impl<'a> System<'a> for Sys {
Some(assets::load_expect_cloned("common.items.weapons.hammer_1")), Some(assets::load_expect_cloned("common.items.weapons.hammer_1")),
); );
} }
loadout = comp::Loadout {
active_item: Some(comp::ItemConfig {
item: assets::load_expect_cloned("common.items.weapons.hammer_1"),
primary_ability: None,
secondary_ability: None,
block_ability: None,
dodge_ability: None,
}),
second_item: None,
};
stats.level.set_level(rand::thread_rng().gen_range(8, 15)); stats.level.set_level(rand::thread_rng().gen_range(8, 15));
scale = 2.0 + rand::random::<f32>(); scale = 2.0 + rand::random::<f32>();
} }
@ -210,12 +231,10 @@ impl<'a> System<'a> for Sys {
stats stats
.health .health
.set_to(stats.health.maximum(), comp::HealthSource::Revive); .set_to(stats.health.maximum(), comp::HealthSource::Revive);
if let Some(item::Item { if let Some(item::ItemKind::Tool(item::ToolData { base_damage, .. })) =
kind: item::ItemKind::Tool(item::ToolData { base_damage, .. }), &mut loadout.active_item.map(|i| i.item.kind)
..
}) = &mut stats.equipment.main
{ {
*base_damage = stats.level.level() as u64 * 3; *base_damage = stats.level.level() as u32 * 3;
} }
server_emitter.emit(ServerEvent::CreateNpc { server_emitter.emit(ServerEvent::CreateNpc {
pos: Pos(entity.pos), pos: Pos(entity.pos),

View File

@ -1659,22 +1659,25 @@ impl Hud {
// Skillbar // Skillbar
// Get player stats // Get player stats
let ecs = client.state().ecs(); let ecs = client.state().ecs();
let stats = ecs.read_storage::<comp::Stats>();
let energy = ecs.read_storage::<comp::Energy>();
let character_state = ecs.read_storage::<comp::CharacterState>();
let entity = client.entity(); let entity = client.entity();
let controller = ecs.read_storage::<comp::Controller>(); let stats = ecs.read_storage::<comp::Stats>();
if let (Some(stats), Some(energy), Some(character_state), Some(controller)) = ( let loadouts = ecs.read_storage::<comp::Loadout>();
let energies = ecs.read_storage::<comp::Energy>();
let character_states = ecs.read_storage::<comp::CharacterState>();
let controllers = ecs.read_storage::<comp::Controller>();
if let (Some(stats), Some(loadout), Some(energy), Some(character_state), Some(controller)) = (
stats.get(entity), stats.get(entity),
energy.get(entity), loadouts.get(entity),
character_state.get(entity), energies.get(entity),
controller.get(entity).map(|c| &c.inputs), character_states.get(entity),
controllers.get(entity).map(|c| &c.inputs),
) { ) {
Skillbar::new( Skillbar::new(
global_state, global_state,
&self.imgs, &self.imgs,
&self.fonts, &self.fonts,
&stats, &stats,
&loadout,
&energy, &energy,
&character_state, &character_state,
self.pulse, self.pulse,

View File

@ -11,7 +11,7 @@ use common::{
assets::load_expect, assets::load_expect,
comp::{ comp::{
item::{DebugKind, ToolData, ToolKind}, item::{DebugKind, ToolData, ToolKind},
CharacterState, ControllerInputs, Energy, ItemKind, Stats, CharacterState, ControllerInputs, Energy, ItemKind, Loadout, Stats,
}, },
}; };
use conrod_core::{ use conrod_core::{
@ -111,6 +111,7 @@ pub struct Skillbar<'a> {
imgs: &'a Imgs, imgs: &'a Imgs,
fonts: &'a ConrodVoxygenFonts, fonts: &'a ConrodVoxygenFonts,
stats: &'a Stats, stats: &'a Stats,
loadout: &'a Loadout,
energy: &'a Energy, energy: &'a Energy,
character_state: &'a CharacterState, character_state: &'a CharacterState,
controller: &'a ControllerInputs, controller: &'a ControllerInputs,
@ -126,6 +127,7 @@ impl<'a> Skillbar<'a> {
imgs: &'a Imgs, imgs: &'a Imgs,
fonts: &'a ConrodVoxygenFonts, fonts: &'a ConrodVoxygenFonts,
stats: &'a Stats, stats: &'a Stats,
loadout: &'a Loadout,
energy: &'a Energy, energy: &'a Energy,
character_state: &'a CharacterState, character_state: &'a CharacterState,
pulse: f32, pulse: f32,
@ -136,6 +138,7 @@ impl<'a> Skillbar<'a> {
imgs, imgs,
fonts, fonts,
stats, stats,
loadout,
energy, energy,
current_resource: ResourceType::Mana, current_resource: ResourceType::Mana,
common: widget::CommonBuilder::default(), common: widget::CommonBuilder::default(),
@ -580,44 +583,52 @@ impl<'a> Widget for Skillbar<'a> {
// M1 Slot // M1 Slot
Image::new(self.imgs.skillbar_slot_big_bg) Image::new(self.imgs.skillbar_slot_big_bg)
.w_h(38.0 * scale, 38.0 * scale) .w_h(38.0 * scale, 38.0 * scale)
.color(match self.stats.equipment.main.as_ref().map(|i| &i.kind) { .color(
Some(ItemKind::Tool(ToolData { kind, .. })) => match kind { match self.loadout.active_item.as_ref().map(|i| &i.item.kind) {
ToolKind::Bow => Some(BG_COLOR_2), Some(ItemKind::Tool(ToolData { kind, .. })) => match kind {
ToolKind::Staff => Some(BG_COLOR_2), ToolKind::Bow => Some(BG_COLOR_2),
ToolKind::Staff => Some(BG_COLOR_2),
_ => Some(BG_COLOR_2),
},
_ => Some(BG_COLOR_2), _ => Some(BG_COLOR_2),
}, },
_ => Some(BG_COLOR_2), )
})
.middle_of(state.ids.m1_slot) .middle_of(state.ids.m1_slot)
.set(state.ids.m1_slot_bg, ui); .set(state.ids.m1_slot_bg, ui);
Button::image(match self.stats.equipment.main.as_ref().map(|i| &i.kind) { Button::image(
Some(ItemKind::Tool(ToolData { kind, .. })) => match kind { match self.loadout.active_item.as_ref().map(|i| &i.item.kind) {
ToolKind::Sword(_) => self.imgs.twohsword_m1, Some(ItemKind::Tool(ToolData { kind, .. })) => match kind {
ToolKind::Hammer => self.imgs.twohhammer_m1, ToolKind::Sword(_) => self.imgs.twohsword_m1,
ToolKind::Axe => self.imgs.twohaxe_m1, ToolKind::Hammer => self.imgs.twohhammer_m1,
ToolKind::Bow => self.imgs.bow_m1, ToolKind::Axe => self.imgs.twohaxe_m1,
ToolKind::Staff => self.imgs.staff_m1, ToolKind::Bow => self.imgs.bow_m1,
ToolKind::Debug(DebugKind::Boost) => self.imgs.flyingrod_m1, ToolKind::Staff => self.imgs.staff_m1,
ToolKind::Debug(DebugKind::Boost) => self.imgs.flyingrod_m1,
_ => self.imgs.twohaxe_m1,
},
_ => self.imgs.twohaxe_m1, _ => self.imgs.twohaxe_m1,
}, },
_ => self.imgs.twohaxe_m1, ) // Insert Icon here
}) // Insert Icon here .w(
.w(match self.stats.equipment.main.as_ref().map(|i| &i.kind) { match self.loadout.active_item.as_ref().map(|i| &i.item.kind) {
Some(ItemKind::Tool(ToolData { kind, .. })) => match kind { Some(ItemKind::Tool(ToolData { kind, .. })) => match kind {
ToolKind::Bow => 30.0 * scale, ToolKind::Bow => 30.0 * scale,
ToolKind::Staff => 32.0 * scale, ToolKind::Staff => 32.0 * scale,
_ => 38.0 * scale,
},
_ => 38.0 * scale, _ => 38.0 * scale,
}, },
_ => 38.0 * scale, )
}) .h(
.h(match self.stats.equipment.main.as_ref().map(|i| &i.kind) { match self.loadout.active_item.as_ref().map(|i| &i.item.kind) {
Some(ItemKind::Tool(ToolData { kind, .. })) => match kind { Some(ItemKind::Tool(ToolData { kind, .. })) => match kind {
ToolKind::Bow => 30.0 * scale, ToolKind::Bow => 30.0 * scale,
ToolKind::Staff => 32.0 * scale, ToolKind::Staff => 32.0 * scale,
_ => 38.0 * scale,
},
_ => 38.0 * scale, _ => 38.0 * scale,
}, },
_ => 38.0 * scale, )
})
.middle_of(state.ids.m1_slot_bg) .middle_of(state.ids.m1_slot_bg)
.set(state.ids.m1_content, ui); .set(state.ids.m1_content, ui);
// M2 Slot // M2 Slot
@ -673,44 +684,52 @@ impl<'a> Widget for Skillbar<'a> {
Image::new(self.imgs.skillbar_slot_big_bg) Image::new(self.imgs.skillbar_slot_big_bg)
.w_h(38.0 * scale, 38.0 * scale) .w_h(38.0 * scale, 38.0 * scale)
.color(match self.stats.equipment.main.as_ref().map(|i| &i.kind) { .color(
Some(ItemKind::Tool(ToolData { kind, .. })) => match kind { match self.loadout.active_item.as_ref().map(|i| &i.item.kind) {
ToolKind::Bow => Some(BG_COLOR_2), Some(ItemKind::Tool(ToolData { kind, .. })) => match kind {
ToolKind::Staff => Some(BG_COLOR_2), ToolKind::Bow => Some(BG_COLOR_2),
ToolKind::Staff => Some(BG_COLOR_2),
_ => Some(BG_COLOR_2),
},
_ => Some(BG_COLOR_2), _ => Some(BG_COLOR_2),
}, },
_ => Some(BG_COLOR_2), )
})
.middle_of(state.ids.m2_slot) .middle_of(state.ids.m2_slot)
.set(state.ids.m2_slot_bg, ui); .set(state.ids.m2_slot_bg, ui);
Button::image(match self.stats.equipment.main.as_ref().map(|i| &i.kind) { Button::image(
Some(ItemKind::Tool(ToolData { kind, .. })) => match kind { match self.loadout.active_item.as_ref().map(|i| &i.item.kind) {
ToolKind::Sword(_) => self.imgs.twohsword_m2, Some(ItemKind::Tool(ToolData { kind, .. })) => match kind {
ToolKind::Hammer => self.imgs.twohhammer_m2, ToolKind::Sword(_) => self.imgs.twohsword_m2,
ToolKind::Axe => self.imgs.twohaxe_m2, ToolKind::Hammer => self.imgs.twohhammer_m2,
ToolKind::Bow => self.imgs.bow_m2, ToolKind::Axe => self.imgs.twohaxe_m2,
ToolKind::Staff => self.imgs.staff_m2, ToolKind::Bow => self.imgs.bow_m2,
ToolKind::Debug(DebugKind::Boost) => self.imgs.flyingrod_m2, ToolKind::Staff => self.imgs.staff_m2,
ToolKind::Debug(DebugKind::Boost) => self.imgs.flyingrod_m2,
_ => self.imgs.twohaxe_m2,
},
_ => self.imgs.twohaxe_m2, _ => self.imgs.twohaxe_m2,
}, },
_ => self.imgs.twohaxe_m2, ) // Insert Icon here
}) // Insert Icon here .w(
.w(match self.stats.equipment.main.as_ref().map(|i| &i.kind) { match self.loadout.active_item.as_ref().map(|i| &i.item.kind) {
Some(ItemKind::Tool(ToolData { kind, .. })) => match kind { Some(ItemKind::Tool(ToolData { kind, .. })) => match kind {
ToolKind::Bow => 30.0 * scale, ToolKind::Bow => 30.0 * scale,
ToolKind::Staff => 30.0 * scale, ToolKind::Staff => 30.0 * scale,
_ => 38.0 * scale,
},
_ => 38.0 * scale, _ => 38.0 * scale,
}, },
_ => 38.0 * scale, )
}) .h(
.h(match self.stats.equipment.main.as_ref().map(|i| &i.kind) { match self.loadout.active_item.as_ref().map(|i| &i.item.kind) {
Some(ItemKind::Tool(ToolData { kind, .. })) => match kind { Some(ItemKind::Tool(ToolData { kind, .. })) => match kind {
ToolKind::Bow => 30.0 * scale, ToolKind::Bow => 30.0 * scale,
ToolKind::Staff => 30.0 * scale, ToolKind::Staff => 30.0 * scale,
_ => 38.0 * scale,
},
_ => 38.0 * scale, _ => 38.0 * scale,
}, },
_ => 38.0 * scale, )
})
.middle_of(state.ids.m2_slot_bg) .middle_of(state.ids.m2_slot_bg)
.set(state.ids.m2_content, ui); .set(state.ids.m2_content, ui);
//Slot 5 //Slot 5

View File

@ -116,14 +116,11 @@ impl PlayState for CharSelectionState {
global_state.window.renderer_mut(), global_state.window.renderer_mut(),
self.client.borrow().get_tick(), self.client.borrow().get_tick(),
humanoid_body.clone(), humanoid_body.clone(),
&comp::Equipment { self.char_selection_ui
main: self .get_character_data()
.char_selection_ui .and_then(|data| data.tool)
.get_character_data() .and_then(|tool| assets::load_cloned::<comp::Item>(&tool).ok())
.and_then(|data| data.tool) .map(|i| i.kind),
.and_then(|tool| assets::load_cloned(&tool).ok()),
alt: None,
},
); );
// Draw the UI to the screen. // Draw the UI to the screen.

View File

@ -6,7 +6,7 @@ use crate::{
}; };
use common::{ use common::{
assets::watch::ReloadIndicator, assets::watch::ReloadIndicator,
comp::{Body, CharacterState, Equipment}, comp::{Body, CharacterState, ItemKind},
}; };
use hashbrown::{hash_map::Entry, HashMap}; use hashbrown::{hash_map::Entry, HashMap};
use std::{ use std::{
@ -19,7 +19,7 @@ enum FigureKey {
Simple(Body), Simple(Body),
Complex( Complex(
Body, Body,
Option<Equipment>, Option<ItemKind>,
CameraMode, CameraMode,
Option<CharacterStateCacheKey>, Option<CharacterStateCacheKey>,
), ),
@ -58,7 +58,7 @@ impl<Skel: Skeleton> FigureModelCache<Skel> {
&mut self, &mut self,
renderer: &mut Renderer, renderer: &mut Renderer,
body: Body, body: Body,
equipment: Option<&Equipment>, item_kind: Option<ItemKind>,
tick: u64, tick: u64,
camera_mode: CameraMode, camera_mode: CameraMode,
character_state: Option<&CharacterState>, character_state: Option<&CharacterState>,
@ -67,10 +67,10 @@ impl<Skel: Skeleton> FigureModelCache<Skel> {
for<'a> &'a common::comp::Body: std::convert::TryInto<Skel::Attr>, for<'a> &'a common::comp::Body: std::convert::TryInto<Skel::Attr>,
Skel::Attr: Default, Skel::Attr: Default,
{ {
let key = if equipment.is_some() { let key = if item_kind.is_some() {
FigureKey::Complex( FigureKey::Complex(
body, body,
equipment.cloned(), item_kind,
camera_mode, camera_mode,
character_state.map(|cs| CharacterStateCacheKey::from(cs)), character_state.map(|cs| CharacterStateCacheKey::from(cs)),
) )
@ -187,7 +187,7 @@ impl<Skel: Skeleton> FigureModelCache<Skel> {
}) })
.unwrap_or_default() .unwrap_or_default()
{ {
Some(mesh_main(equipment.and_then(|e| e.main.as_ref()))) Some(mesh_main(item_kind))
} else { } else {
None None
}, },

View File

@ -534,9 +534,9 @@ impl HumArmorFootSpec {
} }
} }
pub fn mesh_main(item: Option<&Item>) -> Mesh<FigurePipeline> { pub fn mesh_main(item_kind: Option<ItemKind>) -> Mesh<FigurePipeline> {
if let Some(item) = item { if let Some(item_kind) = item_kind {
let (name, offset) = match item.kind { let (name, offset) = match item_kind {
ItemKind::Tool(ToolData { kind, .. }) => match kind { ItemKind::Tool(ToolData { kind, .. }) => match kind {
ToolKind::Sword(_) => ("weapon.sword.rusty_2h", Vec3::new(-1.5, -6.5, -4.0)), ToolKind::Sword(_) => ("weapon.sword.rusty_2h", Vec3::new(-1.5, -6.5, -4.0)),
ToolKind::Axe => ("weapon.axe.rusty_2h", Vec3::new(-1.5, -5.0, -4.0)), ToolKind::Axe => ("weapon.axe.rusty_2h", Vec3::new(-1.5, -5.0, -4.0)),

View File

@ -20,7 +20,8 @@ use crate::{
}; };
use common::{ use common::{
comp::{ comp::{
Body, CharacterState, ItemKind, Last, Ori, PhysicsState, Pos, Scale, Stats, ToolData, Vel, Body, CharacterState, ItemKind, Last, Loadout, Ori, PhysicsState, Pos, Scale, Stats,
ToolData, Vel,
}, },
state::State, state::State,
terrain::TerrainChunk, terrain::TerrainChunk,
@ -112,7 +113,19 @@ impl FigureMgr {
.get(scene_data.player_entity) .get(scene_data.player_entity)
.map_or(Vec3::zero(), |pos| pos.0); .map_or(Vec3::zero(), |pos| pos.0);
for (entity, pos, vel, ori, scale, body, character, last_character, physics, stats) in ( for (
entity,
pos,
vel,
ori,
scale,
body,
character,
last_character,
physics,
stats,
loadout,
) in (
&ecs.entities(), &ecs.entities(),
&ecs.read_storage::<Pos>(), &ecs.read_storage::<Pos>(),
&ecs.read_storage::<Vel>(), &ecs.read_storage::<Vel>(),
@ -123,6 +136,7 @@ impl FigureMgr {
ecs.read_storage::<Last<CharacterState>>().maybe(), ecs.read_storage::<Last<CharacterState>>().maybe(),
&ecs.read_storage::<PhysicsState>(), &ecs.read_storage::<PhysicsState>(),
ecs.read_storage::<Stats>().maybe(), ecs.read_storage::<Stats>().maybe(),
ecs.read_storage::<Loadout>().maybe(),
) )
.join() .join()
{ {
@ -370,11 +384,11 @@ impl FigureMgr {
let mut state_animation_rate = 1.0; let mut state_animation_rate = 1.0;
let active_tool_kind = if let Some(ItemKind::Tool(ToolData { kind, .. })) = stats let active_item_kind = loadout
.and_then(|s| s.equipment.main.as_ref()) .and_then(|l| l.active_item.as_ref())
.map(|i| &i.kind) .map(|i| i.item.kind);
{ let active_tool_kind = if let Some(ItemKind::Tool(tool)) = active_item_kind {
Some(*kind) Some(tool.kind)
} else { } else {
None None
}; };
@ -386,7 +400,7 @@ impl FigureMgr {
.get_or_create_model( .get_or_create_model(
renderer, renderer,
*body, *body,
stats.map(|s| &s.equipment), active_item_kind,
tick, tick,
CameraMode::default(), CameraMode::default(),
None, None,
@ -566,7 +580,7 @@ impl FigureMgr {
.get_or_create_model( .get_or_create_model(
renderer, renderer,
*body, *body,
stats.map(|s| &s.equipment), active_item_kind,
tick, tick,
CameraMode::default(), CameraMode::default(),
None, None,
@ -647,7 +661,7 @@ impl FigureMgr {
.get_or_create_model( .get_or_create_model(
renderer, renderer,
*body, *body,
stats.map(|s| &s.equipment), active_item_kind,
tick, tick,
CameraMode::default(), CameraMode::default(),
None, None,
@ -730,7 +744,7 @@ impl FigureMgr {
.get_or_create_model( .get_or_create_model(
renderer, renderer,
*body, *body,
stats.map(|s| &s.equipment), active_item_kind,
tick, tick,
CameraMode::default(), CameraMode::default(),
None, None,
@ -805,7 +819,7 @@ impl FigureMgr {
.get_or_create_model( .get_or_create_model(
renderer, renderer,
*body, *body,
stats.map(|s| &s.equipment), active_item_kind,
tick, tick,
CameraMode::default(), CameraMode::default(),
None, None,
@ -880,7 +894,7 @@ impl FigureMgr {
.get_or_create_model( .get_or_create_model(
renderer, renderer,
*body, *body,
stats.map(|s| &s.equipment), active_item_kind,
tick, tick,
CameraMode::default(), CameraMode::default(),
None, None,
@ -955,7 +969,7 @@ impl FigureMgr {
.get_or_create_model( .get_or_create_model(
renderer, renderer,
*body, *body,
stats.map(|s| &s.equipment), active_item_kind,
tick, tick,
CameraMode::default(), CameraMode::default(),
None, None,
@ -1030,7 +1044,7 @@ impl FigureMgr {
.get_or_create_model( .get_or_create_model(
renderer, renderer,
*body, *body,
stats.map(|s| &s.equipment), active_item_kind,
tick, tick,
CameraMode::default(), CameraMode::default(),
None, None,
@ -1105,7 +1119,7 @@ impl FigureMgr {
.get_or_create_model( .get_or_create_model(
renderer, renderer,
*body, *body,
stats.map(|s| &s.equipment), active_item_kind,
tick, tick,
CameraMode::default(), CameraMode::default(),
None, None,
@ -1180,7 +1194,7 @@ impl FigureMgr {
.get_or_create_model( .get_or_create_model(
renderer, renderer,
*body, *body,
stats.map(|s| &s.equipment), active_item_kind,
tick, tick,
CameraMode::default(), CameraMode::default(),
None, None,
@ -1313,17 +1327,18 @@ impl FigureMgr {
let character_state_storage = state.read_storage::<common::comp::CharacterState>(); let character_state_storage = state.read_storage::<common::comp::CharacterState>();
let character_state = character_state_storage.get(player_entity); let character_state = character_state_storage.get(player_entity);
for (entity, _, _, body, stats, _) in ( for (entity, _, _, body, stats, loadout, _) in (
&ecs.entities(), &ecs.entities(),
&ecs.read_storage::<Pos>(), &ecs.read_storage::<Pos>(),
ecs.read_storage::<Ori>().maybe(), ecs.read_storage::<Ori>().maybe(),
&ecs.read_storage::<Body>(), &ecs.read_storage::<Body>(),
ecs.read_storage::<Stats>().maybe(), ecs.read_storage::<Stats>().maybe(),
ecs.read_storage::<Loadout>().maybe(),
ecs.read_storage::<Scale>().maybe(), ecs.read_storage::<Scale>().maybe(),
) )
.join() .join()
// Don't render dead entities // Don't render dead entities
.filter(|(_, _, _, _, stats, _)| stats.map_or(true, |s| !s.is_dead)) .filter(|(_, _, _, _, stats, loadout, _)| stats.map_or(true, |s| !s.is_dead))
{ {
let is_player = entity == player_entity; let is_player = entity == player_entity;
let player_camera_mode = if is_player { let player_camera_mode = if is_player {
@ -1331,7 +1346,9 @@ impl FigureMgr {
} else { } else {
CameraMode::default() CameraMode::default()
}; };
let stats = stats.map(|s| &s.equipment); let active_item_kind = loadout
.and_then(|l| l.active_item.as_ref())
.map(|i| i.item.kind);
let character_state = if is_player { character_state } else { None }; let character_state = if is_player { character_state } else { None };
let FigureMgr { let FigureMgr {
@ -1369,7 +1386,7 @@ impl FigureMgr {
.get_or_create_model( .get_or_create_model(
renderer, renderer,
*body, *body,
stats, active_item_kind,
tick, tick,
player_camera_mode, player_camera_mode,
character_state, character_state,
@ -1385,7 +1402,7 @@ impl FigureMgr {
.get_or_create_model( .get_or_create_model(
renderer, renderer,
*body, *body,
stats, active_item_kind,
tick, tick,
player_camera_mode, player_camera_mode,
character_state, character_state,
@ -1401,7 +1418,7 @@ impl FigureMgr {
.get_or_create_model( .get_or_create_model(
renderer, renderer,
*body, *body,
stats, active_item_kind,
tick, tick,
player_camera_mode, player_camera_mode,
character_state, character_state,
@ -1417,7 +1434,7 @@ impl FigureMgr {
.get_or_create_model( .get_or_create_model(
renderer, renderer,
*body, *body,
stats, active_item_kind,
tick, tick,
player_camera_mode, player_camera_mode,
character_state, character_state,
@ -1433,7 +1450,7 @@ impl FigureMgr {
.get_or_create_model( .get_or_create_model(
renderer, renderer,
*body, *body,
stats, active_item_kind,
tick, tick,
player_camera_mode, player_camera_mode,
character_state, character_state,
@ -1449,7 +1466,7 @@ impl FigureMgr {
.get_or_create_model( .get_or_create_model(
renderer, renderer,
*body, *body,
stats, active_item_kind,
tick, tick,
player_camera_mode, player_camera_mode,
character_state, character_state,
@ -1465,7 +1482,7 @@ impl FigureMgr {
.get_or_create_model( .get_or_create_model(
renderer, renderer,
*body, *body,
stats, active_item_kind,
tick, tick,
player_camera_mode, player_camera_mode,
character_state, character_state,
@ -1481,7 +1498,7 @@ impl FigureMgr {
.get_or_create_model( .get_or_create_model(
renderer, renderer,
*body, *body,
stats, active_item_kind,
tick, tick,
player_camera_mode, player_camera_mode,
character_state, character_state,
@ -1497,7 +1514,7 @@ impl FigureMgr {
.get_or_create_model( .get_or_create_model(
renderer, renderer,
*body, *body,
stats, active_item_kind,
tick, tick,
player_camera_mode, player_camera_mode,
character_state, character_state,
@ -1513,7 +1530,7 @@ impl FigureMgr {
.get_or_create_model( .get_or_create_model(
renderer, renderer,
*body, *body,
stats, active_item_kind,
tick, tick,
player_camera_mode, player_camera_mode,
character_state, character_state,
@ -1529,7 +1546,7 @@ impl FigureMgr {
.get_or_create_model( .get_or_create_model(
renderer, renderer,
*body, *body,
stats, active_item_kind,
tick, tick,
player_camera_mode, player_camera_mode,
character_state, character_state,

View File

@ -15,7 +15,7 @@ use crate::{
window::{Event, PressState}, window::{Event, PressState},
}; };
use common::{ use common::{
comp::{humanoid, Body, Equipment}, comp::{humanoid, Body, ItemKind},
terrain::BlockKind, terrain::BlockKind,
vol::{BaseVol, ReadVol, Vox}, vol::{BaseVol, ReadVol, Vox},
}; };
@ -208,7 +208,7 @@ impl Scene {
renderer: &mut Renderer, renderer: &mut Renderer,
tick: u64, tick: u64,
body: Option<humanoid::Body>, body: Option<humanoid::Body>,
equipment: &Equipment, active_item_kind: Option<ItemKind>,
) { ) {
renderer.render_skybox(&self.skybox.model, &self.globals, &self.skybox.locals); renderer.render_skybox(&self.skybox.model, &self.globals, &self.skybox.locals);
@ -218,7 +218,7 @@ impl Scene {
.get_or_create_model( .get_or_create_model(
renderer, renderer,
Body::Humanoid(body), Body::Humanoid(body),
Some(equipment), active_item_kind,
tick, tick,
CameraMode::default(), CameraMode::default(),
None, None,