Did voxygen stuff for ability pool.

This commit is contained in:
Sam 2021-11-09 21:20:41 -05:00
parent d33ff9f17e
commit 4309e1ff9b
7 changed files with 140 additions and 289 deletions

View File

@ -40,10 +40,10 @@ pub const MAX_ABILITIES: usize = 5;
// considerations.
#[derive(Serialize, Deserialize, Debug, Clone)]
pub struct AbilityPool {
primary: Ability,
secondary: Ability,
movement: Ability,
abilities: [Ability; MAX_ABILITIES],
pub primary: Ability,
pub secondary: Ability,
pub movement: Ability,
pub abilities: [Ability; MAX_ABILITIES],
}
impl Component for AbilityPool {

View File

@ -1,9 +1,9 @@
use common::{
comp::{
item::{tool::AbilityMap, MaterialStatManifest},
Auras, BeamSegment, Body, Buffs, CanBuild, CharacterState, Collider, Combo, Density,
Energy, Group, Health, Inventory, Item, LightEmitter, Mass, MountState, Mounting, Ori,
Player, Poise, Pos, Scale, Shockwave, SkillSet, Stats, Sticky, Vel,
AbilityPool, Auras, BeamSegment, Body, Buffs, CanBuild, CharacterState, Collider, Combo,
Density, Energy, Group, Health, Inventory, Item, LightEmitter, Mass, MountState, Mounting,
Ori, Player, Poise, Pos, Scale, Shockwave, SkillSet, Stats, Sticky, Vel,
},
uid::Uid,
};
@ -44,6 +44,7 @@ pub struct TrackedComps<'a> {
pub player: ReadStorage<'a, Player>,
pub stats: ReadStorage<'a, Stats>,
pub skill_set: ReadStorage<'a, SkillSet>,
pub ability_pool: ReadStorage<'a, AbilityPool>,
pub buffs: ReadStorage<'a, Buffs>,
pub auras: ReadStorage<'a, Auras>,
pub energy: ReadStorage<'a, Energy>,
@ -91,6 +92,10 @@ impl<'a> TrackedComps<'a> {
.get(entity)
.cloned()
.map(|c| comps.push(c.into()));
self.ability_pool
.get(entity)
.cloned()
.map(|c| comps.push(c.into()));
self.buffs
.get(entity)
.cloned()
@ -187,6 +192,7 @@ pub struct ReadTrackers<'a> {
pub player: ReadExpect<'a, UpdateTracker<Player>>,
pub stats: ReadExpect<'a, UpdateTracker<Stats>>,
pub skill_set: ReadExpect<'a, UpdateTracker<SkillSet>>,
pub ability_pool: ReadExpect<'a, UpdateTracker<AbilityPool>>,
pub buffs: ReadExpect<'a, UpdateTracker<Buffs>>,
pub auras: ReadExpect<'a, UpdateTracker<Auras>>,
pub energy: ReadExpect<'a, UpdateTracker<Energy>>,
@ -223,6 +229,7 @@ impl<'a> ReadTrackers<'a> {
.with_component(&comps.uid, &*self.player, &comps.player, filter)
.with_component(&comps.uid, &*self.stats, &comps.stats, filter)
.with_component(&comps.uid, &*self.skill_set, &comps.skill_set, filter)
.with_component(&comps.uid, &*self.ability_pool, &comps.ability_pool, filter)
.with_component(&comps.uid, &*self.buffs, &comps.buffs, filter)
.with_component(&comps.uid, &*self.auras, &comps.auras, filter)
.with_component(&comps.uid, &*self.energy, &comps.energy, filter)
@ -266,6 +273,7 @@ pub struct WriteTrackers<'a> {
player: WriteExpect<'a, UpdateTracker<Player>>,
stats: WriteExpect<'a, UpdateTracker<Stats>>,
skill_set: WriteExpect<'a, UpdateTracker<SkillSet>>,
ability_pool: WriteExpect<'a, UpdateTracker<AbilityPool>>,
buffs: WriteExpect<'a, UpdateTracker<Buffs>>,
auras: WriteExpect<'a, UpdateTracker<Auras>>,
energy: WriteExpect<'a, UpdateTracker<Energy>>,
@ -296,6 +304,7 @@ fn record_changes(comps: &TrackedComps, trackers: &mut WriteTrackers) {
trackers.player.record_changes(&comps.player);
trackers.stats.record_changes(&comps.stats);
trackers.skill_set.record_changes(&comps.skill_set);
trackers.ability_pool.record_changes(&comps.ability_pool);
trackers.buffs.record_changes(&comps.buffs);
trackers.auras.record_changes(&comps.auras);
trackers.energy.record_changes(&comps.energy);
@ -341,6 +350,7 @@ fn record_changes(comps: &TrackedComps, trackers: &mut WriteTrackers) {
log_counts!(player, "Players");
log_counts!(stats, "Stats");
log_counts!(skill_set, "SkillSet");
log_counts!(ability_pool, "AbilityPool");
log_counts!(energy, "Energies");
log_counts!(combo, "Combos");
log_vounts!(health, "Healths");
@ -367,6 +377,7 @@ pub fn register_trackers(world: &mut World) {
world.register_tracker::<Player>();
world.register_tracker::<Stats>();
world.register_tracker::<SkillSet>();
world.register_tracker::<AbilityPool>();
world.register_tracker::<Buffs>();
world.register_tracker::<Auras>();
world.register_tracker::<Energy>();

View File

@ -1,9 +1,4 @@
use crate::hud::slots::EquipSlot;
use common::comp::{
item::{tool::Hands, ItemKind},
slot::InvSlotId,
Inventory,
};
use common::comp::slot::InvSlotId;
use serde::{Deserialize, Serialize};
#[derive(Clone, Copy, Debug, PartialEq)]
@ -23,8 +18,7 @@ pub enum Slot {
#[derive(Clone, Copy, PartialEq, Debug, Serialize, Deserialize)]
pub enum SlotContents {
Inventory(InvSlotId),
Ability3,
Ability4,
Ability(usize),
}
#[derive(Clone, Copy, Default)]
@ -59,120 +53,32 @@ impl State {
self.slots[slot as usize] = Some(SlotContents::Inventory(inventory_pos));
}
// TODO: remove
// Adds ability3 slot if it is missing and should be present
// Removes if it is there and shouldn't be present
pub fn maintain_ability3(&mut self, client: &client::Client) {
// TODO: remove pending UI
// Adds ability slots if missing and should be present
// Removes ability slots if not there and shouldn't be present
pub fn maintain_abilities(&mut self, client: &client::Client) {
use specs::WorldExt;
let inventories = client.state().ecs().read_storage::<Inventory>();
let inventory = inventories.get(client.entity());
let skill_sets = client
if let Some(ability_pool) = client
.state()
.ecs()
.read_storage::<common::comp::SkillSet>();
let skill_set = skill_sets.get(client.entity());
let hands =
|equip_slot| match inventory.and_then(|i| i.equipped(equip_slot).map(|i| i.kind())) {
Some(ItemKind::Tool(tool)) => Some(tool.hands),
_ => None,
};
let equip_slot = match (
hands(EquipSlot::ActiveMainhand),
hands(EquipSlot::ActiveOffhand),
) {
(Some(_), _) => Some(EquipSlot::ActiveMainhand),
(_, Some(_)) => Some(EquipSlot::ActiveOffhand),
_ => None,
};
let should_be_present = if let (Some(inventory), Some(skill_set), Some(equip_slot)) =
(inventory, skill_set, equip_slot)
.read_storage::<common::comp::AbilityPool>()
.get(client.entity())
{
inventory.equipped(equip_slot).map_or(false, |i| {
i.item_config_expect()
.abilities
.abilities
.get(0)
.as_ref()
.map_or(false, |(s, _)| s.map_or(true, |s| skill_set.has_skill(s)))
})
} else {
false
};
if should_be_present {
if !self
.slots
.iter()
.any(|s| matches!(s, Some(SlotContents::Ability3)))
{
self.slots[0] = Some(SlotContents::Ability3);
use common::comp::Ability;
for (i, ability) in ability_pool.abilities.iter().enumerate() {
if matches!(ability, Ability::Empty) {
self.slots
.iter_mut()
.filter(|s| matches!(s, Some(SlotContents::Ability(index)) if *index == i))
.for_each(|s| *s = None)
} else if let Some(slot) = self
.slots
.iter_mut()
.find(|s| !matches!(s, Some(SlotContents::Ability(index)) if *index != i))
{
*slot = Some(SlotContents::Ability(i));
}
}
} else {
self.slots
.iter_mut()
.filter(|s| matches!(s, Some(SlotContents::Ability3)))
.for_each(|s| *s = None)
}
}
pub fn maintain_ability4(&mut self, client: &client::Client) {
use specs::WorldExt;
let inventories = client.state().ecs().read_storage::<Inventory>();
let inventory = inventories.get(client.entity());
let skill_sets = client
.state()
.ecs()
.read_storage::<common::comp::SkillSet>();
let skill_set = skill_sets.get(client.entity());
let should_be_present = if let (Some(inventory), Some(skill_set)) = (inventory, skill_set) {
let hands = |equip_slot| match inventory.equipped(equip_slot).map(|i| i.kind()) {
Some(ItemKind::Tool(tool)) => Some(tool.hands),
_ => None,
};
let active_tool_hands = hands(EquipSlot::ActiveMainhand);
let second_tool_hands = hands(EquipSlot::ActiveOffhand);
let (equip_slot, skill_index) = match (active_tool_hands, second_tool_hands) {
(Some(Hands::Two), _) => (Some(EquipSlot::ActiveMainhand), 1),
(Some(_), Some(Hands::One)) => (Some(EquipSlot::ActiveOffhand), 0),
(Some(Hands::One), _) => (Some(EquipSlot::ActiveMainhand), 1),
(None, Some(_)) => (Some(EquipSlot::ActiveOffhand), 1),
(_, _) => (None, 0),
};
if let Some(equip_slot) = equip_slot {
inventory.equipped(equip_slot).map_or(false, |i| {
i.item_config_expect()
.abilities
.abilities
.get(skill_index)
.as_ref()
.map_or(false, |(s, _)| s.map_or(true, |s| skill_set.has_skill(s)))
})
} else {
false
}
} else {
false
};
if should_be_present {
if !self
.slots
.iter()
.any(|s| matches!(s, Some(SlotContents::Ability4)))
{
self.slots[1] = Some(SlotContents::Ability4);
}
} else {
self.slots
.iter_mut()
.filter(|s| matches!(s, Some(SlotContents::Ability4)))
.for_each(|s| *s = None)
}
}
}

View File

@ -512,8 +512,7 @@ pub enum Event {
SortInventory,
ChangeHotbarState(Box<HotbarState>),
TradeAction(TradeAction),
Ability3(bool),
Ability4(bool),
Ability(usize, bool),
Logout,
Quit,
@ -2639,6 +2638,7 @@ impl Hud {
let inventories = ecs.read_storage::<comp::Inventory>();
let energies = ecs.read_storage::<comp::Energy>();
let skillsets = ecs.read_storage::<comp::SkillSet>();
let ability_pools = ecs.read_storage::<comp::AbilityPool>();
let character_states = ecs.read_storage::<comp::CharacterState>();
let controllers = ecs.read_storage::<comp::Controller>();
let bodies = ecs.read_storage::<comp::Body>();
@ -2664,6 +2664,8 @@ impl Hud {
Some(inventory),
Some(energy),
Some(skillset),
Some(ability_pool),
Some(body),
Some(_character_state),
Some(_controller),
) = (
@ -2671,6 +2673,8 @@ impl Hud {
inventories.get(entity),
energies.get(entity),
skillsets.get(entity),
ability_pools.get(entity),
bodies.get(entity),
character_states.get(entity),
controllers.get(entity).map(|c| &c.inputs),
) {
@ -2685,6 +2689,8 @@ impl Hud {
inventory,
energy,
skillset,
ability_pool,
body,
//&character_state,
self.pulse,
//&controller,
@ -3358,18 +3364,14 @@ impl Hud {
}
} else if let Hotbar(h) = from {
// Used from hotbar
self.hotbar.get(h).map(|s| {
match s {
hotbar::SlotContents::Inventory(i) => {
events.push(Event::UseSlot {
slot: comp::slot::Slot::Inventory(i),
bypass_dialog: false,
});
},
hotbar::SlotContents::Ability3 | hotbar::SlotContents::Ability4 => {
}, /* Event::Ability3(true),
* sticks */
}
self.hotbar.get(h).map(|s| match s {
hotbar::SlotContents::Inventory(i) => {
events.push(Event::UseSlot {
slot: comp::slot::Slot::Inventory(i),
bypass_dialog: false,
});
},
hotbar::SlotContents::Ability(_) => {},
});
}
},
@ -3496,8 +3498,7 @@ impl Hud {
},
}
}
self.hotbar.maintain_ability3(client);
self.hotbar.maintain_ability4(client);
self.hotbar.maintain_abilities(client);
events
}
@ -3577,8 +3578,7 @@ impl Hud {
});
}
},
hotbar::SlotContents::Ability3 => events.push(Event::Ability3(state)),
hotbar::SlotContents::Ability4 => events.push(Event::Ability4(state)),
hotbar::SlotContents::Ability(i) => events.push(Event::Ability(i, state)),
});
}
}

View File

@ -26,7 +26,7 @@ use common::comp::{
tool::{Tool, ToolKind},
Hands, Item, ItemDesc, ItemKind, MaterialStatManifest,
},
Energy, Health, Inventory, SkillSet,
AbilityPool, Body, Energy, Health, Inventory, SkillSet,
};
use conrod_core::{
color,
@ -253,6 +253,8 @@ pub struct Skillbar<'a> {
inventory: &'a Inventory,
energy: &'a Energy,
skillset: &'a SkillSet,
ability_pool: &'a AbilityPool,
body: &'a Body,
// character_state: &'a CharacterState,
// controller: &'a ControllerInputs,
hotbar: &'a hotbar::State,
@ -280,6 +282,8 @@ impl<'a> Skillbar<'a> {
inventory: &'a Inventory,
energy: &'a Energy,
skillset: &'a SkillSet,
ability_pool: &'a AbilityPool,
body: &'a Body,
// character_state: &'a CharacterState,
pulse: f32,
// controller: &'a ControllerInputs,
@ -302,6 +306,8 @@ impl<'a> Skillbar<'a> {
inventory,
energy,
skillset,
ability_pool,
body,
common: widget::CommonBuilder::default(),
// character_state,
pulse,
@ -511,7 +517,14 @@ impl<'a> Skillbar<'a> {
let key_layout = &self.global_state.window.key_layout;
// TODO: avoid this
let content_source = (self.hotbar, self.inventory, self.energy, self.skillset);
let content_source = (
self.hotbar,
self.inventory,
self.energy,
self.skillset,
self.ability_pool,
self.body,
);
let image_source = (self.item_imgs, self.imgs);
let mut slot_maker = SlotMaker {
@ -591,45 +604,26 @@ impl<'a> Skillbar<'a> {
// Helper
let tooltip_text = |slot| {
let (hotbar, inventory, ..) = content_source;
let (hotbar, inventory, _, _, ability_pool, _) = content_source;
hotbar.get(slot).and_then(|content| match content {
hotbar::SlotContents::Inventory(i) => inventory
.get(i)
.map(|item| (item.name(), item.description())),
hotbar::SlotContents::Ability3 => inventory
.equipped(EquipSlot::ActiveMainhand)
.map(|i| i.kind())
.and_then(|kind| match kind {
ItemKind::Tool(Tool { kind, .. }) => ability_description(kind),
_ => None,
}),
hotbar::SlotContents::Ability4 => {
let hands = |equip_slot| match inventory.equipped(equip_slot).map(|i| i.kind())
{
Some(ItemKind::Tool(tool)) => Some(tool.hands),
_ => None,
};
let active_tool_hands = hands(EquipSlot::ActiveMainhand);
let second_tool_hands = hands(EquipSlot::ActiveOffhand);
let equip_slot = match (active_tool_hands, second_tool_hands) {
(Some(Hands::Two), _) => Some(EquipSlot::ActiveMainhand),
(Some(_), Some(Hands::One)) => Some(EquipSlot::ActiveOffhand),
(Some(Hands::One), _) => Some(EquipSlot::ActiveMainhand),
(None, Some(_)) => Some(EquipSlot::ActiveOffhand),
(_, _) => None,
};
equip_slot.and_then(|equip_slot| {
inventory
.equipped(equip_slot)
.map(|i| i.kind())
.and_then(|kind| match kind {
ItemKind::Tool(Tool { kind, .. }) => ability_description(kind),
_ => None,
})
})
hotbar::SlotContents::Ability(i) => {
use comp::Ability;
ability_pool
.abilities
.get(i)
.and_then(|a| match a {
Ability::MainWeaponAbility(_) => Some(EquipSlot::ActiveMainhand),
Ability::OffWeaponAbility(_) => Some(EquipSlot::ActiveOffhand),
_ => None,
})
.and_then(|equip_slot| inventory.equipped(equip_slot))
.and_then(|item| match &item.kind {
ItemKind::Tool(Tool { kind, .. }) => ability_description(kind),
_ => None,
})
},
})
};

View File

@ -5,12 +5,14 @@ use super::{
};
use crate::ui::slot::{self, SlotKey, SumSlot};
use common::comp::{
self,
controller::InputKind,
item::{
tool::{Hands, ToolKind},
tool::{Tool, ToolKind},
ItemKind,
},
slot::InvSlotId,
Energy, Inventory, SkillSet,
AbilityPool, Body, Energy, Inventory, SkillSet,
};
use conrod_core::{image, Color};
use specs::Entity as EcsEntity;
@ -122,7 +124,14 @@ pub enum HotbarImage {
SceptreAura,
}
type HotbarSource<'a> = (&'a hotbar::State, &'a Inventory, &'a Energy, &'a SkillSet);
type HotbarSource<'a> = (
&'a hotbar::State,
&'a Inventory,
&'a Energy,
&'a SkillSet,
&'a AbilityPool,
&'a Body,
);
type HotbarImageSource<'a> = (&'a ItemImgs, &'a img_ids::Imgs);
impl<'a> SlotKey<HotbarSource<'a>, HotbarImageSource<'a>> for HotbarSlot {
@ -130,120 +139,59 @@ impl<'a> SlotKey<HotbarSource<'a>, HotbarImageSource<'a>> for HotbarSlot {
fn image_key(
&self,
(hotbar, inventory, energy, skillset): &HotbarSource<'a>,
(hotbar, inventory, energy, skillset, ability_pool, body): &HotbarSource<'a>,
) -> Option<(Self::ImageKey, Option<Color>)> {
hotbar.get(*self).and_then(|contents| match contents {
hotbar::SlotContents::Inventory(idx) => inventory
.get(idx)
.map(|item| HotbarImage::Item(item.into()))
.map(|i| (i, None)),
hotbar::SlotContents::Ability3 => {
let hands = |equip_slot| match inventory.equipped(equip_slot).map(|i| i.kind()) {
Some(ItemKind::Tool(tool)) => Some(tool.hands),
_ => None,
};
let active_tool_hands = hands(EquipSlot::ActiveMainhand);
let second_tool_hands = hands(EquipSlot::ActiveOffhand);
let equip_slot = match (active_tool_hands, second_tool_hands) {
(Some(_), _) => Some(EquipSlot::ActiveMainhand),
(None, Some(_)) => Some(EquipSlot::ActiveOffhand),
(_, _) => None,
};
let tool =
equip_slot.and_then(|es| match inventory.equipped(es).map(|i| (i, i.kind())) {
Some((item, ItemKind::Tool(tool))) => Some((item, tool)),
hotbar::SlotContents::Ability(i) => {
use comp::Ability;
let tool_kind = ability_pool
.abilities
.get(i)
.and_then(|a| match a {
Ability::MainWeaponAbility(_) => Some(EquipSlot::ActiveMainhand),
Ability::OffWeaponAbility(_) => Some(EquipSlot::ActiveOffhand),
_ => None,
})
.and_then(|equip_slot| inventory.equipped(equip_slot))
.and_then(|item| match &item.kind {
ItemKind::Tool(Tool { kind, .. }) => Some(kind),
_ => None,
});
tool.and_then(|(item, tool)| {
hotbar_image(tool.kind).map(|i| {
(
i,
if let Some(skill) =
item.item_config_expect().abilities.abilities.get(0)
{
if energy.current()
>= skill
.1
.clone()
.adjusted_by_skills(skillset, Some(tool.kind))
.get_energy_cost()
{
Some(Color::Rgba(1.0, 1.0, 1.0, 1.0))
} else {
Some(Color::Rgba(0.3, 0.3, 0.3, 0.8))
}
} else {
Some(Color::Rgba(1.0, 1.0, 1.0, 1.0))
},
)
tool_kind
.and_then(|kind| hotbar_image(*kind))
.and_then(|image| {
ability_pool
.activate_ability(
InputKind::Ability(i),
Some(inventory),
skillset,
body,
)
.map(|(ability, _)| {
(
image,
if energy.current() > ability.get_energy_cost() {
Some(Color::Rgba(1.0, 1.0, 1.0, 1.0))
} else {
Some(Color::Rgba(0.3, 0.3, 0.3, 0.8))
},
)
})
})
})
},
hotbar::SlotContents::Ability4 => {
let hands = |equip_slot| match inventory.equipped(equip_slot).map(|i| i.kind()) {
Some(ItemKind::Tool(tool)) => Some(tool.hands),
_ => None,
};
let active_tool_hands = hands(EquipSlot::ActiveMainhand);
let second_tool_hands = hands(EquipSlot::ActiveOffhand);
let (equip_slot, skill_index) = match (active_tool_hands, second_tool_hands) {
(Some(Hands::Two), _) => (Some(EquipSlot::ActiveMainhand), 1),
(Some(_), Some(Hands::One)) => (Some(EquipSlot::ActiveOffhand), 0),
(Some(Hands::One), _) => (Some(EquipSlot::ActiveMainhand), 1),
(None, Some(_)) => (Some(EquipSlot::ActiveOffhand), 1),
(_, _) => (None, 0),
};
let tool =
match equip_slot.and_then(|es| inventory.equipped(es).map(|i| (i, i.kind()))) {
Some((item, ItemKind::Tool(tool))) => Some((item, tool)),
_ => None,
};
tool.and_then(|(item, tool)| {
hotbar_image(tool.kind).map(|i| {
(
i,
if let Some(skill) = item
.item_config_expect()
.abilities
.abilities
.get(skill_index)
{
if energy.current()
>= skill
.1
.clone()
.adjusted_by_skills(skillset, Some(tool.kind))
.get_energy_cost()
{
Some(Color::Rgba(1.0, 1.0, 1.0, 1.0))
} else {
Some(Color::Rgba(0.3, 0.3, 0.3, 0.8))
}
} else {
Some(Color::Rgba(1.0, 1.0, 1.0, 1.0))
},
)
})
})
},
})
}
fn amount(&self, (hotbar, inventory, _, _): &HotbarSource<'a>) -> Option<u32> {
fn amount(&self, (hotbar, inventory, _, _, _, _): &HotbarSource<'a>) -> Option<u32> {
hotbar
.get(*self)
.and_then(|content| match content {
hotbar::SlotContents::Inventory(idx) => inventory.get(idx),
hotbar::SlotContents::Ability3 => None,
hotbar::SlotContents::Ability4 => None,
hotbar::SlotContents::Ability(_) => None,
})
.map(|item| item.amount())
.filter(|amount| *amount > 1)

View File

@ -1370,17 +1370,9 @@ impl PlayState for SessionState {
HudEvent::TradeAction(action) => {
self.client.borrow_mut().perform_trade_action(action);
},
HudEvent::Ability3(state) => {
HudEvent::Ability(i, state) => {
self.client.borrow_mut().handle_input(
InputKind::Ability(0),
state,
default_select_pos,
self.target_entity,
);
},
HudEvent::Ability4(state) => {
self.client.borrow_mut().handle_input(
InputKind::Ability(1),
InputKind::Ability(i),
state,
default_select_pos,
self.target_entity,