mirror of
https://gitlab.com/veloren/veloren.git
synced 2024-08-30 18:12:32 +00:00
Merge branch 'juliancoffee/bigger-kit' into 'master'
Make /kit use all weapons from possible modulars See merge request veloren/veloren!3595
This commit is contained in:
commit
34fa03a425
@ -28,7 +28,6 @@
|
||||
(2, Item("common.items.weapons.axe.parashu")),
|
||||
(2, Item("common.items.weapons.bow.sagitta")),
|
||||
(2, Item("common.items.weapons.staff.laevateinn")),
|
||||
(1, Item("common.items.weapons.sceptre.root_evil")),
|
||||
(1, Item("common.items.weapons.sceptre.caduceus")),
|
||||
]), None)),
|
||||
)),
|
||||
@ -39,4 +38,4 @@
|
||||
meta: [
|
||||
SkillSetAsset("common.skillset.preset.rank5.fullskill"),
|
||||
],
|
||||
)
|
||||
)
|
||||
|
@ -74,25 +74,6 @@
|
||||
(Item("common.items.armor.misc.ring.gold"), 2),
|
||||
(Item("common.items.armor.cultist.ring"), 2),
|
||||
],
|
||||
"endgame": [
|
||||
// Cultist weapons
|
||||
(Item("common.items.weapons.hammer.cultist_purp_2h-0"),1),
|
||||
(Item("common.items.weapons.staff.cultist_staff"),1),
|
||||
(Item("common.items.weapons.sword.cultist"),1),
|
||||
(Item("common.items.weapons.bow.velorite"),1),
|
||||
(Item("common.items.weapons.axe.malachite_axe-0"),1),
|
||||
(Item("common.items.weapons.sceptre.sceptre_velorite_0"),1),
|
||||
|
||||
// Legendaries
|
||||
(Item("common.items.weapons.hammer.mjolnir"),1),
|
||||
(Item("common.items.weapons.staff.laevateinn"),1),
|
||||
(Item("common.items.weapons.sword.caladbolg"),1),
|
||||
(Item("common.items.weapons.bow.sagitta"),1),
|
||||
(Item("common.items.weapons.axe.parashu"),1),
|
||||
(Item("common.items.weapons.sceptre.caduceus"),1),
|
||||
(Item("common.items.weapons.sceptre.root_evil"),1),
|
||||
|
||||
],
|
||||
"tier-5": [
|
||||
// Hide
|
||||
(Item("common.items.armor.hide.dragonscale.back"), 1),
|
||||
@ -129,6 +110,14 @@
|
||||
(ModularWeapon(tool: Staff, material: Eldwood),1),
|
||||
(ModularWeapon(tool: Sceptre, material: Eldwood),1),
|
||||
|
||||
// Legendaries
|
||||
(Item("common.items.weapons.hammer.mjolnir"),1),
|
||||
(Item("common.items.weapons.staff.laevateinn"),1),
|
||||
(Item("common.items.weapons.sword.caladbolg"),1),
|
||||
(Item("common.items.weapons.bow.sagitta"),1),
|
||||
(Item("common.items.weapons.axe.parashu"),1),
|
||||
(Item("common.items.weapons.sceptre.caduceus"),1),
|
||||
|
||||
// Potion Kit
|
||||
(Item("common.items.consumable.potion_med"), 100),
|
||||
],
|
||||
@ -337,6 +326,14 @@
|
||||
(Item("common.items.armor.ferocious.back"),1),
|
||||
],
|
||||
"cultist": [
|
||||
// Cultist weapons
|
||||
(Item("common.items.weapons.hammer.cultist_purp_2h-0"),1),
|
||||
(Item("common.items.weapons.staff.cultist_staff"),1),
|
||||
(Item("common.items.weapons.sword.cultist"),1),
|
||||
(Item("common.items.weapons.bow.velorite"),1),
|
||||
(Item("common.items.weapons.axe.malachite_axe-0"),1),
|
||||
(Item("common.items.weapons.sceptre.sceptre_velorite_0"),1),
|
||||
// Clothes
|
||||
(Item("common.items.armor.cultist.chest"), 1),
|
||||
(Item("common.items.armor.cultist.pants"), 1),
|
||||
(Item("common.items.armor.cultist.hand"), 1),
|
||||
|
@ -317,24 +317,37 @@ lazy_static! {
|
||||
static ref PRIMARY_COMPONENT_POOL: PrimaryComponentPool = {
|
||||
let mut component_pool = HashMap::new();
|
||||
|
||||
// Load recipe book (done to check that material is valid for a particular component)
|
||||
// Load recipe book
|
||||
// (done to check that material is valid for a particular component)
|
||||
use crate::recipe::ComponentKey;
|
||||
let recipes = recipe::default_component_recipe_book().read();
|
||||
let ability_map = &AbilityMap::load().read();
|
||||
let msm = &MaterialStatManifest::load().read();
|
||||
|
||||
recipes
|
||||
.iter()
|
||||
.for_each(|(ComponentKey { toolkind, material, .. }, recipe)| {
|
||||
recipes.iter().for_each(
|
||||
|(
|
||||
ComponentKey {
|
||||
toolkind, material, ..
|
||||
},
|
||||
recipe,
|
||||
)| {
|
||||
let component = recipe.item_output(ability_map, msm);
|
||||
let hand_restriction = if let ItemKind::ModularComponent(ModularComponent::ToolPrimaryComponent { hand_restriction, .. }) = &*component.kind() {
|
||||
*hand_restriction
|
||||
} else {
|
||||
return;
|
||||
};
|
||||
let entry = component_pool.entry((*toolkind, String::from(material))).or_insert(Vec::new());
|
||||
let hand_restriction =
|
||||
if let ItemKind::ModularComponent(ModularComponent::ToolPrimaryComponent {
|
||||
hand_restriction,
|
||||
..
|
||||
}) = &*component.kind()
|
||||
{
|
||||
*hand_restriction
|
||||
} else {
|
||||
return;
|
||||
};
|
||||
let entry = component_pool
|
||||
.entry((*toolkind, String::from(material)))
|
||||
.or_insert(Vec::new());
|
||||
entry.push((component, hand_restriction));
|
||||
});
|
||||
},
|
||||
);
|
||||
|
||||
component_pool
|
||||
};
|
||||
@ -352,7 +365,12 @@ lazy_static! {
|
||||
.filter_map(|comp| Some(comp.item_definition_id().itemdef_id()?.to_owned()))
|
||||
.filter_map(|id| Arc::<ItemDef>::load_cloned(&id).ok())
|
||||
.for_each(|comp_def| {
|
||||
if let ItemKind::ModularComponent(ModularComponent::ToolSecondaryComponent { hand_restriction, .. }) = comp_def.kind {
|
||||
if let ItemKind::ModularComponent(
|
||||
ModularComponent::ToolSecondaryComponent {
|
||||
hand_restriction, ..
|
||||
},
|
||||
) = comp_def.kind
|
||||
{
|
||||
let entry = component_pool.entry(toolkind).or_insert(Vec::new());
|
||||
entry.push((Arc::clone(&comp_def), hand_restriction));
|
||||
}
|
||||
@ -371,14 +389,49 @@ pub enum ModularWeaponCreationError {
|
||||
SecondaryComponentNotFound,
|
||||
}
|
||||
|
||||
/// Check if hand restrictions are compatible.
|
||||
///
|
||||
/// If at least on of them is omitted, check is passed.
|
||||
fn compatible_handndess(a: Option<Hands>, b: Option<Hands>) -> bool {
|
||||
match (a, b) {
|
||||
(Some(a), Some(b)) => a == b,
|
||||
_ => true,
|
||||
}
|
||||
}
|
||||
|
||||
/// Generate all primary components for specific tool and material.
|
||||
///
|
||||
/// Read [random_weapon_primary_component] for more.
|
||||
pub fn generate_weapon_primary_components(
|
||||
tool: ToolKind,
|
||||
material: Material,
|
||||
hand_restriction: Option<Hands>,
|
||||
) -> Result<Vec<(Item, Option<Hands>)>, ModularWeaponCreationError> {
|
||||
if let Some(material_id) = material.asset_identifier() {
|
||||
// Loads default ability map and material stat manifest for later use
|
||||
let ability_map = &AbilityMap::load().read();
|
||||
let msm = &MaterialStatManifest::load().read();
|
||||
|
||||
Ok(PRIMARY_COMPONENT_POOL
|
||||
.get(&(tool, material_id.to_owned()))
|
||||
.into_iter()
|
||||
.flatten()
|
||||
.filter(|(_comp, hand)| compatible_handndess(hand_restriction, *hand))
|
||||
.map(|(c, h)| (c.duplicate(ability_map, msm), hand_restriction.or(*h)))
|
||||
.collect())
|
||||
} else {
|
||||
Err(ModularWeaponCreationError::MaterialNotFound)
|
||||
}
|
||||
}
|
||||
|
||||
/// Creates a random modular weapon primary component when provided with a
|
||||
/// toolkind, material, and optionally the handedness
|
||||
///
|
||||
/// Note: The component produced is not necessarily restricted to that
|
||||
/// NOTE: The component produced is not necessarily restricted to that
|
||||
/// handedness, but rather is able to produce a weapon of that handedness
|
||||
/// depending on what secondary component is used
|
||||
///
|
||||
/// Returns the comptabile handednesses that can be used with provided
|
||||
/// Returns the compatible handednesses that can be used with provided
|
||||
/// restriction and generated component (useful for cases where no restriction
|
||||
/// was passed in, but generated component has a restriction)
|
||||
pub fn random_weapon_primary_component(
|
||||
@ -387,7 +440,7 @@ pub fn random_weapon_primary_component(
|
||||
hand_restriction: Option<Hands>,
|
||||
mut rng: &mut impl Rng,
|
||||
) -> Result<(Item, Option<Hands>), ModularWeaponCreationError> {
|
||||
let result = (|| {
|
||||
let result = {
|
||||
if let Some(material_id) = material.asset_identifier() {
|
||||
// Loads default ability map and material stat manifest for later use
|
||||
let ability_map = &AbilityMap::load().read();
|
||||
@ -397,10 +450,7 @@ pub fn random_weapon_primary_component(
|
||||
.get(&(tool, material_id.to_owned()))
|
||||
.into_iter()
|
||||
.flatten()
|
||||
.filter(|(_comp, hand)| match (hand_restriction, hand) {
|
||||
(Some(restriction), Some(hand)) => restriction == *hand,
|
||||
(None, _) | (_, None) => true,
|
||||
})
|
||||
.filter(|(_comp, hand)| compatible_handndess(hand_restriction, *hand))
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
let (comp, hand) = primary_components
|
||||
@ -411,7 +461,8 @@ pub fn random_weapon_primary_component(
|
||||
} else {
|
||||
Err(ModularWeaponCreationError::MaterialNotFound)
|
||||
}
|
||||
})();
|
||||
};
|
||||
|
||||
if let Err(err) = &result {
|
||||
let error_str = format!(
|
||||
"Failed to synthesize a primary component for a modular {tool:?} made of {material:?} \
|
||||
@ -422,6 +473,45 @@ pub fn random_weapon_primary_component(
|
||||
result
|
||||
}
|
||||
|
||||
pub fn generate_weapons(
|
||||
tool: ToolKind,
|
||||
material: Material,
|
||||
hand_restriction: Option<Hands>,
|
||||
) -> Result<Vec<Item>, ModularWeaponCreationError> {
|
||||
// Loads default ability map and material stat manifest for later use
|
||||
let ability_map = &AbilityMap::load().read();
|
||||
let msm = &MaterialStatManifest::load().read();
|
||||
|
||||
let primaries = generate_weapon_primary_components(tool, material, hand_restriction)?;
|
||||
let mut weapons = Vec::new();
|
||||
|
||||
for (comp, comp_hand) in primaries {
|
||||
let secondaries = SECONDARY_COMPONENT_POOL
|
||||
.get(&tool)
|
||||
.into_iter()
|
||||
.flatten()
|
||||
.filter(|(_def, hand)| compatible_handndess(hand_restriction, *hand))
|
||||
.filter(|(_def, hand)| compatible_handndess(comp_hand, *hand));
|
||||
|
||||
for (def, _hand) in secondaries {
|
||||
let secondary = Item::new_from_item_base(
|
||||
ItemBase::Simple(Arc::clone(def)),
|
||||
Vec::new(),
|
||||
ability_map,
|
||||
msm,
|
||||
);
|
||||
weapons.push(Item::new_from_item_base(
|
||||
ItemBase::Modular(ModularBase::Tool),
|
||||
vec![comp.duplicate(ability_map, msm), secondary],
|
||||
ability_map,
|
||||
msm,
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
Ok(weapons)
|
||||
}
|
||||
|
||||
/// Creates a random modular weapon when provided with a toolkind, material, and
|
||||
/// optionally the handedness
|
||||
pub fn random_weapon(
|
||||
@ -430,7 +520,7 @@ pub fn random_weapon(
|
||||
hand_restriction: Option<Hands>,
|
||||
mut rng: &mut impl Rng,
|
||||
) -> Result<Item, ModularWeaponCreationError> {
|
||||
let result = (|| {
|
||||
let result = {
|
||||
// Loads default ability map and material stat manifest for later use
|
||||
let ability_map = &AbilityMap::load().read();
|
||||
let msm = &MaterialStatManifest::load().read();
|
||||
@ -442,10 +532,7 @@ pub fn random_weapon(
|
||||
.get(&tool)
|
||||
.into_iter()
|
||||
.flatten()
|
||||
.filter(|(_def, hand)| match (hand_restriction, hand) {
|
||||
(Some(restriction), Some(hand)) => restriction == *hand,
|
||||
(None, _) | (_, None) => true,
|
||||
})
|
||||
.filter(|(_def, hand)| compatible_handndess(hand_restriction, *hand))
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
let secondary_component = {
|
||||
@ -453,6 +540,7 @@ pub fn random_weapon(
|
||||
.choose(&mut rng)
|
||||
.ok_or(ModularWeaponCreationError::SecondaryComponentNotFound)?
|
||||
.0;
|
||||
|
||||
Item::new_from_item_base(
|
||||
ItemBase::Simple(Arc::clone(def)),
|
||||
Vec::new(),
|
||||
@ -468,7 +556,7 @@ pub fn random_weapon(
|
||||
ability_map,
|
||||
msm,
|
||||
))
|
||||
})();
|
||||
};
|
||||
if let Err(err) = &result {
|
||||
let error_str = format!(
|
||||
"Failed to synthesize a modular {tool:?} made of {material:?} that had a hand \
|
||||
|
@ -1944,51 +1944,72 @@ where
|
||||
if target_inventory.free_slots() < count {
|
||||
return Err("Inventory doesn't have enough slots".to_owned());
|
||||
}
|
||||
let mut rng = thread_rng();
|
||||
for (item_id, quantity) in kit {
|
||||
let mut item = match &item_id {
|
||||
KitSpec::Item(item_id) => Item::new_from_asset(item_id)
|
||||
.map_err(|_| format!("Unknown item: {:#?}", item_id))?,
|
||||
KitSpec::ModularWeapon { tool, material } => {
|
||||
comp::item::modular::random_weapon(*tool, *material, None, &mut rng)
|
||||
.map_err(|err| format!("{:#?}", err))?
|
||||
},
|
||||
};
|
||||
let mut res = Ok(());
|
||||
|
||||
// Either push stack or push one by one.
|
||||
if item.is_stackable() {
|
||||
// FIXME: in theory, this can fail,
|
||||
// but we don't have stack sizes yet.
|
||||
let _ = item.set_amount(quantity);
|
||||
res = target_inventory.push(item);
|
||||
for (item_id, quantity) in kit {
|
||||
push_item(item_id, quantity, server, &mut |item| {
|
||||
let res = target_inventory.push(item);
|
||||
let _ = target_inv_update.insert(
|
||||
target,
|
||||
comp::InventoryUpdate::new(comp::InventoryUpdateEvent::Debug),
|
||||
);
|
||||
} else {
|
||||
let ability_map = server.state.ecs().read_resource::<AbilityMap>();
|
||||
let msm = server.state.ecs().read_resource::<MaterialStatManifest>();
|
||||
for _ in 0..quantity {
|
||||
res = target_inventory.push(item.duplicate(&ability_map, &msm));
|
||||
let _ = target_inv_update.insert(
|
||||
target,
|
||||
comp::InventoryUpdate::new(comp::InventoryUpdateEvent::Debug),
|
||||
);
|
||||
}
|
||||
}
|
||||
// I think it's possible to pick-up item during this loop
|
||||
// and fail into case where you had space but now you don't?
|
||||
if res.is_err() {
|
||||
return Err("Can't fit item to inventory".to_owned());
|
||||
}
|
||||
|
||||
res
|
||||
})?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
} else {
|
||||
Err("Could not get inventory".to_string())
|
||||
}
|
||||
}
|
||||
|
||||
fn push_item(
|
||||
item_id: KitSpec,
|
||||
quantity: u32,
|
||||
server: &Server,
|
||||
push: &mut dyn FnMut(Item) -> Result<(), Item>,
|
||||
) -> CmdResult<()> {
|
||||
let items = match &item_id {
|
||||
KitSpec::Item(item_id) => vec![
|
||||
Item::new_from_asset(item_id).map_err(|_| format!("Unknown item: {:#?}", item_id))?,
|
||||
],
|
||||
KitSpec::ModularWeapon { tool, material } => {
|
||||
comp::item::modular::generate_weapons(*tool, *material, None)
|
||||
.map_err(|err| format!("{:#?}", err))?
|
||||
},
|
||||
};
|
||||
|
||||
let mut res = Ok(());
|
||||
for mut item in items {
|
||||
// Either push stack or push one by one.
|
||||
if item.is_stackable() {
|
||||
// FIXME: in theory, this can fail,
|
||||
// but we don't have stack sizes yet.
|
||||
let _ = item.set_amount(quantity);
|
||||
res = push(item);
|
||||
} else {
|
||||
let ability_map = server.state.ecs().read_resource::<AbilityMap>();
|
||||
let msm = server.state.ecs().read_resource::<MaterialStatManifest>();
|
||||
|
||||
for _ in 0..quantity {
|
||||
res = push(item.duplicate(&ability_map, &msm));
|
||||
|
||||
if res.is_err() {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// I think it's possible to pick-up item during this loop
|
||||
// and fail into case where you had space but now you don't?
|
||||
if res.is_err() {
|
||||
return Err("Can't fit item to inventory".to_owned());
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn handle_object(
|
||||
server: &mut Server,
|
||||
client: EcsEntity,
|
||||
|
Loading…
Reference in New Issue
Block a user