Initial crafting UI for modular weapons.

This commit is contained in:
Sam 2021-12-11 15:28:37 -05:00
parent bf348b7f43
commit 8fc0138e84
6 changed files with 756 additions and 462 deletions

View File

@ -1081,7 +1081,7 @@ impl Client {
&mut self,
slot_a: InvSlotId,
slot_b: InvSlotId,
sprite_pos: Vec3<i32>,
sprite_pos: Option<Vec3<i32>>,
) -> bool {
let inventories = self.inventories();
let inventory = inventories.get(self.entity());
@ -1122,7 +1122,7 @@ impl Client {
primary_component,
secondary_component,
},
craft_sprite: Some(sprite_pos),
craft_sprite: sprite_pos,
},
)));
true

View File

@ -760,7 +760,7 @@ impl<'a> Widget for Bag<'a> {
true,
inventory,
&state.bg_ids,
self.show.salvage,
self.show.crafting_fields.salvage,
)
.set(state.ids.inventory_scroller, ui);

File diff suppressed because it is too large Load Diff

View File

@ -533,6 +533,11 @@ pub enum Event {
slot: InvSlotId,
salvage_pos: Vec3<i32>,
},
CraftModularWeapon {
primary_slot: InvSlotId,
secondary_slot: InvSlotId,
craft_sprite: Option<(Vec3<i32>, SpriteKind)>,
},
InviteMember(Uid),
AcceptInvite,
DeclineInvite,
@ -692,9 +697,7 @@ pub struct Show {
chat_tab_settings_index: Option<usize>,
settings_tab: SettingsTab,
diary_fields: diary::DiaryShow,
crafting_tab: CraftingTab,
crafting_search_key: Option<String>,
craft_sprite: Option<(Vec3<i32>, SpriteKind)>,
crafting_fields: crafting::CraftingShow,
social_search_key: Option<String>,
want_grab: bool,
stats: bool,
@ -703,7 +706,6 @@ pub struct Show {
camera_clamp: bool,
prompt_dialog: Option<PromptDialogSettings>,
location_markers: MapMarkers,
salvage: bool,
trade_amount_input_key: Option<TradeAmountInput>,
}
impl Show {
@ -712,7 +714,7 @@ impl Show {
self.bag = open;
self.map = false;
self.want_grab = !open;
self.salvage = false;
self.crafting_fields.salvage = false;
if !open {
self.crafting = false;
@ -734,7 +736,7 @@ impl Show {
self.map = open;
self.bag = false;
self.crafting = false;
self.salvage = false;
self.crafting_fields.salvage = false;
self.social = false;
self.diary = false;
self.want_grab = !open;
@ -760,7 +762,7 @@ impl Show {
self.search_crafting_recipe(None);
}
self.crafting = open;
self.salvage = false;
self.crafting_fields.salvage = false;
self.bag = open;
self.map = false;
self.want_grab = !open;
@ -774,16 +776,18 @@ impl Show {
) {
self.selected_crafting_tab(tab);
self.crafting(true);
self.craft_sprite = self.craft_sprite.or(craft_sprite);
self.salvage = matches!(self.craft_sprite, Some((_, SpriteKind::DismantlingBench)))
&& matches!(tab, CraftingTab::Dismantle);
self.crafting_fields.craft_sprite = self.crafting_fields.craft_sprite.or(craft_sprite);
self.crafting_fields.salvage = matches!(
self.crafting_fields.craft_sprite,
Some((_, SpriteKind::DismantlingBench))
) && matches!(tab, CraftingTab::Dismantle);
}
fn diary(&mut self, open: bool) {
if !self.esc_menu {
self.social = false;
self.crafting = false;
self.salvage = false;
self.crafting_fields.salvage = false;
self.bag = false;
self.map = false;
self.diary_fields = diary::DiaryShow::default();
@ -802,7 +806,7 @@ impl Show {
self.bag = false;
self.social = false;
self.crafting = false;
self.salvage = false;
self.crafting_fields.salvage = false;
self.diary = false;
self.want_grab = !open;
}
@ -894,10 +898,12 @@ impl Show {
self.social = false;
}
fn selected_crafting_tab(&mut self, sel_cat: CraftingTab) { self.crafting_tab = sel_cat; }
fn selected_crafting_tab(&mut self, sel_cat: CraftingTab) {
self.crafting_fields.crafting_tab = sel_cat;
}
fn search_crafting_recipe(&mut self, search_key: Option<String>) {
self.crafting_search_key = search_key;
self.crafting_fields.crafting_search_key = search_key;
}
fn search_social_players(&mut self, search_key: Option<String>) {
@ -1106,9 +1112,7 @@ impl Hud {
chat_tab_settings_index: None,
settings_tab: SettingsTab::Interface,
diary_fields: diary::DiaryShow::default(),
crafting_tab: CraftingTab::All,
crafting_search_key: None,
craft_sprite: None,
crafting_fields: crafting::CraftingShow::default(),
social_search_key: None,
want_grab: true,
ingame: true,
@ -1118,7 +1122,6 @@ impl Hud {
camera_clamp: false,
prompt_dialog: None,
location_markers: MapMarkers::default(),
salvage: false,
trade_amount_input_key: None,
},
to_focus: None,
@ -2930,6 +2933,7 @@ impl Hud {
self.pulse,
&self.rot_imgs,
item_tooltip_manager,
&mut self.slot_manager,
&self.item_imgs,
inventory,
&msm,
@ -2942,7 +2946,17 @@ impl Hud {
crafting::Event::CraftRecipe(recipe) => {
events.push(Event::CraftRecipe {
recipe,
craft_sprite: self.show.craft_sprite,
craft_sprite: self.show.crafting_fields.craft_sprite,
});
},
crafting::Event::CraftModularWeapon {
primary_slot,
secondary_slot,
} => {
events.push(Event::CraftModularWeapon {
primary_slot,
secondary_slot,
craft_sprite: self.show.crafting_fields.craft_sprite,
});
},
crafting::Event::Close => {
@ -3352,6 +3366,7 @@ impl Hud {
Hotbar(_) => None,
Trade(_) => None,
Ability(_) => None,
Crafting(_) => None,
};
match event {
slot::Event::Dragged(a, b) => {
@ -3428,6 +3443,17 @@ impl Hud {
},
(AbilitySlot::Ability(_), AbilitySlot::Ability(_)) => {},
}
} else if let (Inventory(i), Crafting(c)) = (a, b) {
// Add item to crafting input
if (c.requirement)(inventories.get(client.entity()), i.slot) {
self.show
.crafting_fields
.recipe_inputs
.insert(c.index, i.slot);
}
} else if let (Crafting(c), Inventory(_)) = (a, b) {
// Remove item from crafting input
self.show.crafting_fields.recipe_inputs.remove(&c.index);
}
},
slot::Event::Dropped(from) => {
@ -3535,11 +3561,14 @@ impl Hud {
slot::Event::Used(from) => {
// Item used (selected and then clicked again)
if let Some(from) = to_slot(from) {
if self.show.salvage
&& matches!(self.show.crafting_tab, CraftingTab::Dismantle)
if self.show.crafting_fields.salvage
&& matches!(
self.show.crafting_fields.crafting_tab,
CraftingTab::Dismantle
)
{
if let (Slot::Inventory(slot), Some((salvage_pos, _sprite_kind))) =
(from, self.show.craft_sprite)
(from, self.show.crafting_fields.craft_sprite)
{
events.push(Event::SalvageItem { slot, salvage_pos })
}
@ -3575,6 +3604,9 @@ impl Hud {
});
} else if let Ability(AbilitySlot::Slot(index)) = from {
events.push(Event::ChangeAbility(index, AuxiliaryAbility::Empty));
} else if let Crafting(c) = from {
// Remove item from crafting input
self.show.crafting_fields.recipe_inputs.remove(&c.index);
}
},
slot::Event::Request {
@ -4232,14 +4264,15 @@ impl Hud {
}
// Stop selecting a sprite to perform crafting with when out of range
self.show.craft_sprite = self.show.craft_sprite.filter(|(pos, _)| {
self.show.crafting
&& if let Some(player_pos) = client.position() {
pos.map(|e| e as f32 + 0.5).distance(player_pos) < MAX_PICKUP_RANGE
} else {
false
}
});
self.show.crafting_fields.craft_sprite =
self.show.crafting_fields.craft_sprite.filter(|(pos, _)| {
self.show.crafting
&& if let Some(player_pos) = client.position() {
pos.map(|e| e as f32 + 0.5).distance(player_pos) < MAX_PICKUP_RANGE
} else {
false
}
});
// Optimization: skip maintaining UI when it's off.
if !self.show.ui {

View File

@ -12,6 +12,7 @@ use common::comp::{
};
use conrod_core::{image, Color};
use specs::Entity as EcsEntity;
use std::fmt::{Debug, Formatter};
pub use common::comp::slot::{ArmorSlot, EquipSlot};
@ -22,6 +23,7 @@ pub enum SlotKind {
Hotbar(HotbarSlot),
Trade(TradeSlot),
Ability(AbilitySlot),
Crafting(CraftSlot),
/* Spellbook(SpellbookSlot), TODO */
}
@ -233,6 +235,46 @@ impl<'a> SlotKey<AbilitiesSource<'a>, img_ids::Imgs> for AbilitySlot {
}
}
#[derive(Clone, Copy)]
pub struct CraftSlot {
pub index: u32,
pub invslot: Option<InvSlotId>,
pub requirement: fn(Option<&Inventory>, InvSlotId) -> bool,
pub required_amount: u32,
}
impl PartialEq for CraftSlot {
fn eq(&self, other: &Self) -> bool {
(self.index, self.invslot, self.required_amount)
== (other.index, other.invslot, other.required_amount)
}
}
impl Debug for CraftSlot {
fn fmt(&self, _: &mut Formatter<'_>) -> Result<(), std::fmt::Error> { todo!() }
}
impl SlotKey<Inventory, ItemImgs> for CraftSlot {
type ImageKey = ItemKey;
fn image_key(&self, source: &Inventory) -> Option<(Self::ImageKey, Option<Color>)> {
self.invslot
.and_then(|invslot| source.get(invslot))
.map(|i| (i.into(), None))
}
fn amount(&self, source: &Inventory) -> Option<u32> {
self.invslot
.and_then(|invslot| source.get(invslot))
.map(|item| self.required_amount.min(item.amount()))
.filter(|amount| *amount > 1)
}
fn image_ids(key: &Self::ImageKey, source: &ItemImgs) -> Vec<image::Id> {
source.img_ids_or_not_found_img(key.clone())
}
}
impl From<InventorySlot> for SlotKind {
fn from(inventory: InventorySlot) -> Self { Self::Inventory(inventory) }
}
@ -244,6 +286,7 @@ impl From<EquipSlot> for SlotKind {
impl From<HotbarSlot> for SlotKind {
fn from(hotbar: HotbarSlot) -> Self { Self::Hotbar(hotbar) }
}
impl From<TradeSlot> for SlotKind {
fn from(trade: TradeSlot) -> Self { Self::Trade(trade) }
}
@ -252,6 +295,10 @@ impl From<AbilitySlot> for SlotKind {
fn from(ability: AbilitySlot) -> Self { Self::Ability(ability) }
}
impl From<CraftSlot> for SlotKind {
fn from(craft: CraftSlot) -> Self { Self::Crafting(craft) }
}
impl SumSlot for SlotKind {
fn drag_size(&self) -> Option<[f64; 2]> {
Some(match self {

View File

@ -1420,6 +1420,17 @@ impl PlayState for SessionState {
.craft_recipe(&recipe, slots, craft_sprite);
}
},
HudEvent::CraftModularWeapon {
primary_slot,
secondary_slot,
craft_sprite,
} => {
self.client.borrow_mut().craft_modular_weapon(
primary_slot,
secondary_slot,
craft_sprite.map(|(pos, _sprite)| pos),
);
},
HudEvent::SalvageItem { slot, salvage_pos } => {
self.client.borrow_mut().salvage_item(slot, salvage_pos);
},