Merge branch 'snowram/consumables-buffs' into 'master'

Allows for consumables to have an optional array of buffs and effects

See merge request veloren/veloren!1472
This commit is contained in:
Samuel Keiffer
2020-11-06 02:42:34 +00:00
39 changed files with 435 additions and 160 deletions

View File

@ -1,9 +1,11 @@
ItemDef( ItemDef(
name: "Flask of Velorite Dust", name: "Flask of Velorite Dust",
description: "Increases Exp by 250\n\nTake with plenty of water\n\n<Right-Click to use>", description: "Increases Exp by 250\n\nTake with plenty of water",
kind: Consumable( kind: Consumable(
kind: "PotionExp", kind: "PotionExp",
effect: Xp(250), effect: [
Xp(250),
]
), ),
quality: High, quality: High,
) )

View File

@ -1,12 +1,21 @@
ItemDef( ItemDef(
name: "Potent Potion", name: "Potent Potion",
description: "A potent healing potion.\n\nRestores 100 health on use.\n\n<Right-Click to use>", description: "A potent healing potion.\n\nRestores 100 health on use",
kind: Consumable( kind: Consumable(
kind: "Potion", kind: "Potion",
effect: Health(( effect: [
amount: 1000, Buff((
cause: Item, kind: Saturation,
)), data: (
strength: 1000.0,
duration: Some((
secs: 1,
nanos: 0,
)),
),
cat_ids: [Natural],
)),
]
), ),
quality: High, quality: High,
) )

View File

@ -1,9 +1,11 @@
ItemDef( ItemDef(
name: "Potion of Skill", name: "Potion of Skill",
description: "Provides 250 XP to the drinker\n\n<Right-Click to use>", description: "Provides 250 XP to the drinker",
kind: Consumable( kind: Consumable(
kind: "Potion", kind: "Potion",
effect: Xp(250), effect: [
Xp(250),
]
), ),
quality: High, quality: High,
) )

View File

@ -3,10 +3,19 @@ ItemDef(
description: "Restores 100 Health", description: "Restores 100 Health",
kind: Consumable( kind: Consumable(
kind: "PotionLarge", kind: "PotionLarge",
effect: Health(( effect: [
amount: 1000, Buff((
cause: Item, kind: Potion,
)), data: (
strength: 1000.0,
duration: Some((
secs: 1,
nanos: 0,
)),
),
cat_ids: [Natural],
)),
]
), ),
quality: Common, quality: Common,
) )

View File

@ -3,10 +3,19 @@ ItemDef(
description: "Restores 70 Health", description: "Restores 70 Health",
kind: Consumable( kind: Consumable(
kind: "PotionMed", kind: "PotionMed",
effect: Health(( effect: [
amount: 700, Buff((
cause: Item, kind: Potion,
)), data: (
strength: 700.0,
duration: Some((
secs: 1,
nanos: 0,
)),
),
cat_ids: [Natural],
)),
]
), ),
quality: Common, quality: Common,
) )

View File

@ -3,10 +3,19 @@ ItemDef(
description: "Restores 50 Health", description: "Restores 50 Health",
kind: Consumable( kind: Consumable(
kind: "PotionMinor", kind: "PotionMinor",
effect: Health(( effect: [
amount: 500, Buff((
cause: Item, kind: Potion,
)), data: (
strength: 500.0,
duration: Some((
secs: 1,
nanos: 0,
)),
),
cat_ids: [Natural],
)),
]
), ),
quality: Common, quality: Common,
) )

View File

@ -1,12 +1,21 @@
ItemDef( ItemDef(
name: "Apple", name: "Apple",
description: "Restores 10 Health\n\nRed and juicy", description: "Restores 10 Health over 20 seconds\n\nRed and juicy",
kind: Consumable( kind: Consumable(
kind: "Apple", kind: "Apple",
effect: Health(( effect: [
amount: 100, Buff((
cause: Item, kind: Saturation,
)), data: (
strength: 5.0,
duration: Some((
secs: 20,
nanos: 0,
)),
),
cat_ids: [Natural],
)),
]
), ),
quality: Common, quality: Common,
) )

View File

@ -1,12 +1,21 @@
ItemDef( ItemDef(
name: "Mushroom Curry", name: "Mushroom Curry",
description: "Restores 120 Health\n\nWho could say no to that?", description: "Restores 120 Health over 20 seconds\n\nWho could say no to that?",
kind: Consumable( kind: Consumable(
kind: "AppleShroomCurry", kind: "AppleShroomCurry",
effect: Health(( effect: [
amount: 1200, Buff((
cause: Item, kind: Saturation,
)), data: (
strength: 60.0,
duration: Some((
secs: 20,
nanos: 0,
)),
),
cat_ids: [Natural],
)),
]
), ),
quality: Moderate, quality: Moderate,
) )

View File

@ -1,12 +1,21 @@
ItemDef( ItemDef(
name: "Apple Stick", name: "Apple Stick",
description: "Restores 25 Health\n\nThe stick makes it easier to carry!", description: "Restores 25 Health over 20 seconds\n\nThe stick makes it easier to carry!",
kind: Consumable( kind: Consumable(
kind: "AppleStick", kind: "AppleStick",
effect: Health(( effect: [
amount: 250, Buff((
cause: Item, kind: Saturation,
)), data: (
strength: 12.5,
duration: Some((
secs: 20,
nanos: 0,
)),
),
cat_ids: [Natural],
)),
]
), ),
quality: Common, quality: Common,
) )

View File

@ -1,12 +1,21 @@
ItemDef( ItemDef(
name: "Dwarven Cheese", name: "Dwarven Cheese",
description: "Restores 15 Health\n\nAromatic and nutritious", description: "Restores 15 Health over 20 seconds\n\nAromatic and nutritious",
kind: Consumable( kind: Consumable(
kind: "Cheese", kind: "Cheese",
effect: Health(( effect: [
amount: 150, Buff((
cause: Item, kind: Saturation,
)), data: (
strength: 7.5,
duration: Some((
secs: 20,
nanos: 0,
)),
),
cat_ids: [Natural],
)),
]
), ),
quality: Common, quality: Common,
) )

View File

@ -1,12 +1,21 @@
ItemDef( ItemDef(
name: "Coconut", name: "Coconut",
description: "Restores 20 health\n\nReliable source of water and fat", description: "Restores 20 health over 20 seconds\n\nReliable source of water and fat",
kind: Consumable( kind: Consumable(
kind: "Coconut", kind: "Coconut",
effect: Health(( effect: [
amount: 200, Buff((
cause: Item, kind: Saturation,
)), data: (
strength: 10.0,
duration: Some((
secs: 20,
nanos: 0,
)),
),
cat_ids: [Natural],
)),
]
), ),
quality: Common, quality: Common,
) )

View File

@ -1,12 +1,21 @@
ItemDef( ItemDef(
name: "Mushroom", name: "Mushroom",
description: "Restores 5 Health\n\nHopefully this one is not poisonous", description: "Restores 5 Health over 10 seconds\n\nHopefully this one is not poisonous",
kind: Consumable( kind: Consumable(
kind: "Mushroom", kind: "Mushroom",
effect: Health(( effect: [
amount: 50, Buff((
cause: Item, kind: Saturation,
)), data: (
strength: 5.0,
duration: Some((
secs: 10,
nanos: 0,
)),
),
cat_ids: [Natural],
)),
]
), ),
quality: Common, quality: Common,
) )

View File

@ -1,12 +1,21 @@
ItemDef( ItemDef(
name: "Mushroom Stick", name: "Mushroom Stick",
description: "Restores 20 Health\n\nRoasted mushrooms on a stick for easy carrying.", description: "Restores 20 Health over 20 seconds\n\nRoasted mushrooms on a stick for easy carrying",
kind: Consumable( kind: Consumable(
kind: "MushroomStick", kind: "MushroomStick",
effect: Health(( effect: [
amount: 200, Buff((
cause: Item, kind: Saturation,
)), data: (
strength: 10.0,
duration: Some((
secs: 20,
nanos: 0,
)),
),
cat_ids: [Natural],
)),
]
), ),
quality: Common, quality: Common,
) )

View File

@ -1,12 +1,21 @@
ItemDef( ItemDef(
name: "Sunflower Ice Tea", name: "Sunflower Ice Tea",
description: "Restores 50 Health\n\nBrewed from freshly shelled sunflower seeds.", description: "Restores 50 Health over 20 seconds\n\nBrewed from freshly shelled sunflower seeds",
kind: Consumable( kind: Consumable(
kind: "SunflowerTea", kind: "SunflowerTea",
effect: Health(( effect: [
amount: 500, Buff((
cause: Item, kind: Saturation,
)), data: (
strength: 25.0,
duration: Some((
secs: 20,
nanos: 0,
)),
),
cat_ids: [Natural],
)),
]
), ),
quality: Moderate, quality: Moderate,
) )

View File

@ -3,7 +3,9 @@ ItemDef(
description: "Increases Exp by 20\n\nJust a slight touch makes you feel the knowledge of ancient times", description: "Increases Exp by 20\n\nJust a slight touch makes you feel the knowledge of ancient times",
kind: Consumable( kind: Consumable(
kind: "Velorite", kind: "Velorite",
effect: Xp(20), effect: [
Xp(20),
]
), ),
quality: High, quality: High,
) )

View File

@ -3,7 +3,9 @@ ItemDef(
description: "Increases Exp by 10\n\nSmall runes sparkle on its surface", description: "Increases Exp by 10\n\nSmall runes sparkle on its surface",
kind: Consumable( kind: Consumable(
kind: "VeloriteFrag", kind: "VeloriteFrag",
effect: Xp(10), effect: [
Xp(10),
]
), ),
quality: Moderate, quality: Moderate,
) )

View File

@ -6,7 +6,7 @@
// Ore and more // Ore and more
"velorite_frag": (("common.items.ore.veloritefrag", 2), [("common.items.ore.velorite", 1), ("common.items.crafting_tools.craftsman_hammer", 0)]), "velorite_frag": (("common.items.ore.veloritefrag", 2), [("common.items.ore.velorite", 1), ("common.items.crafting_tools.craftsman_hammer", 0)]),
//Potions //Potions
"potion_s": (("common.items.consumable.potion_minor", 1), [("common.items.crafting_ing.empty_vial", 1), ("common.items.ore.veloritefrag", 2)]), "potion_s": (("common.items.consumable.potion_minor", 1), [("common.items.crafting_ing.empty_vial", 1), ("common.items.food.apple", 4), ("common.items.crafting_ing.honey", 1)]),
"potion_m": (("common.items.consumable.potion_med", 1), [("common.items.consumable.potion_minor", 2), ("common.items.ore.veloritefrag", 4)]), "potion_m": (("common.items.consumable.potion_med", 1), [("common.items.consumable.potion_minor", 2), ("common.items.ore.veloritefrag", 4)]),
"collar_basic": (("common.items.utility.collar", 1), [("common.items.crafting_ing.leather_scraps", 5), ("common.items.crafting_ing.shiny_gem", 1)]), "collar_basic": (("common.items.utility.collar", 1), [("common.items.crafting_ing.leather_scraps", 5), ("common.items.crafting_ing.shiny_gem", 1)]),
"bomb_coconut": (("common.items.utility.bomb", 1), [("common.items.crafting_ing.stones", 10), ("common.items.food.coconut", 2), ("common.items.ore.veloritefrag", 2), ("common.items.crafting_tools.mortar_pestle", 0)]), "bomb_coconut": (("common.items.utility.bomb", 1), [("common.items.crafting_ing.stones", 10), ("common.items.food.coconut", 2), ("common.items.ore.veloritefrag", 2), ("common.items.crafting_tools.mortar_pestle", 0)]),

View File

@ -383,6 +383,30 @@
], ],
threshold: 0.3, threshold: 0.3,
), ),
Inventory(Consumed("PotionMed")): (
files: [
"voxygen.audio.sfx.inventory.consumable.liquid",
],
threshold: 0.3,
),
Inventory(Consumed("PotionLarge")): (
files: [
"voxygen.audio.sfx.inventory.consumable.liquid",
],
threshold: 0.3,
),
Inventory(Consumed("PotionExp")): (
files: [
"voxygen.audio.sfx.inventory.consumable.liquid",
],
threshold: 0.3,
),
Inventory(Consumed("SunflowerTea")): (
files: [
"voxygen.audio.sfx.inventory.consumable.liquid",
],
threshold: 0.3,
),
Inventory(Consumed("Apple")): ( Inventory(Consumed("Apple")): (
files: [ files: [
"voxygen.audio.sfx.inventory.consumable.apple", "voxygen.audio.sfx.inventory.consumable.apple",
@ -401,6 +425,42 @@
], ],
threshold: 0.3, threshold: 0.3,
), ),
Inventory(Consumed("AppleShroomCurry")): (
files: [
"voxygen.audio.sfx.inventory.consumable.food",
],
threshold: 0.3,
),
Inventory(Consumed("AppleStick")): (
files: [
"voxygen.audio.sfx.inventory.consumable.food",
],
threshold: 0.3,
),
Inventory(Consumed("Coconut")): (
files: [
"voxygen.audio.sfx.inventory.consumable.food",
],
threshold: 0.3,
),
Inventory(Consumed("MushroomStick")): (
files: [
"voxygen.audio.sfx.inventory.consumable.food",
],
threshold: 0.3,
),
Inventory(Consumed("Velorite")): (
files: [
"voxygen.audio.sfx.inventory.consumable.food",
],
threshold: 0.3,
),
Inventory(Consumed("VeloriteFrag")): (
files: [
"voxygen.audio.sfx.inventory.consumable.food",
],
threshold: 0.3,
),
Explosion: ( Explosion: (
files: [ files: [
// in code // in code

BIN
assets/voxygen/element/icons/de_buffs/buff_potion_0.png (Stored with Git LFS) Normal file

Binary file not shown.

BIN
assets/voxygen/element/icons/de_buffs/buff_saturation_0.png (Stored with Git LFS) Normal file

Binary file not shown.

View File

@ -513,11 +513,11 @@ Willenskraft
"buff.title.missing": "Fehlender Titel", "buff.title.missing": "Fehlender Titel",
"buff.desc.missing": "Fehlende Beschreibung", "buff.desc.missing": "Fehlende Beschreibung",
// Buffs // Buffs
"buff.title.heal_test": "HoT Buff Test", "buff.title.heal": "HoT Buff Test",
"buff.desc.heal_test": "HoT Buff Test", "buff.desc.heal": "HoT Buff Test",
// Debuffs // Debuffs
"debuff.title.bleed_test": "Blutung", "debuff.title.bleed": "Blutung",
"debuff.desc.bleed_test": "Fügt regelmäßig Schaden zu.", "debuff.desc.bleed": "Fügt regelmäßig Schaden zu.",
}, },
vector_map: { vector_map: {

View File

@ -184,7 +184,7 @@ https://account.veloren.net."#,
"hud.chat.pvp_ranged_kill_msg": "[{attacker}] shot [{victim}]", "hud.chat.pvp_ranged_kill_msg": "[{attacker}] shot [{victim}]",
"hud.chat.pvp_explosion_kill_msg": "[{attacker}] blew up [{victim}]", "hud.chat.pvp_explosion_kill_msg": "[{attacker}] blew up [{victim}]",
"hud.chat.pvp_energy_kill_msg": "[{attacker}] killed [{victim}] with magic", "hud.chat.pvp_energy_kill_msg": "[{attacker}] killed [{victim}] with magic",
"hud.chat.pvp_other_kill_msg": "[{attacker}] killed [{victim}]", "hud.chat.pvp_buff_kill_msg": "[{attacker}] killed [{victim}]",
"hud.chat.npc_melee_kill_msg": "{attacker} killed [{victim}]", "hud.chat.npc_melee_kill_msg": "{attacker} killed [{victim}]",
@ -520,11 +520,15 @@ Protection
"buff.title.missing": "Missing Title", "buff.title.missing": "Missing Title",
"buff.desc.missing": "Missing Description", "buff.desc.missing": "Missing Description",
// Buffs // Buffs
"buff.title.heal_test": "Heal Test", "buff.title.heal": "Heal",
"buff.desc.heal_test": "This is a test buff to test healing.", "buff.desc.heal": "Gain health over time.",
"buff.title.potion": "Potion",
"buff.desc.potion": "Drinking...",
"buff.title.saturation": "Saturation",
"buff.desc.saturation": "Gain health over time from consumables.",
// Debuffs // Debuffs
"debuff.title.bleed_test": "Bleeding", "debuff.title.bleed": "Bleeding",
"debuff.desc.bleed_test": "Inflicts regular damage.", "debuff.desc.bleed": "Inflicts regular damage.",
}, },

View File

@ -520,11 +520,11 @@ Koruma
"buff.title.missing": "İsim Yok", "buff.title.missing": "İsim Yok",
"buff.desc.missing": "Açıklama Yok", "buff.desc.missing": "Açıklama Yok",
// Buffs // Buffs
"buff.title.heal_test": "İyileştirme Testi", "buff.title.heal": "İyileştirme Testi",
"buff.desc.heal_test": "Bu etki iyileştirmeyi test etmek için.", "buff.desc.heal": "Bu etki iyileştirmeyi test etmek için.",
// Debuffs // Debuffs
"debuff.title.bleed_test": "Kanama", "debuff.title.bleed": "Kanama",
"debuff.desc.bleed_test": "Normal hasar verir.", "debuff.desc.bleed": "Normal hasar verir.",
}, },
vector_map: { vector_map: {

View File

@ -1983,4 +1983,26 @@ Beehive: Some((
], ],
wind_sway: 0.1, wind_sway: 0.1,
)), )),
// Empty Flask
VialEmpty: Some((
variations: [
(
model: "voxygen.voxel.object.potion_empty",
offset: (-5.0, -5.0, 0.0),
lod_axes: (1.0, 1.0, 1.0),
),
],
wind_sway: 0.0,
)),
// Minor Potion
PotionMinor: Some((
variations: [
(
model: "voxygen.voxel.object.potion_red",
offset: (-5.0, -5.0, 0.0),
lod_axes: (1.0, 1.0, 1.0),
),
],
wind_sway: 0.0,
)),
) )

View File

@ -276,7 +276,7 @@ impl Body {
_ => 1000, _ => 1000,
}, },
Body::Object(_) => 10000, Body::Object(_) => 10000,
Body::Golem(_) => 2560, Body::Golem(_) => 2740,
Body::Theropod(_) => 50, Body::Theropod(_) => 50,
Body::QuadrupedLow(quadruped_low) => match quadruped_low.species { Body::QuadrupedLow(quadruped_low) => match quadruped_low.species {
quadruped_low::Species::Crocodile => 600, quadruped_low::Species::Crocodile => 600,

View File

@ -10,11 +10,15 @@ use std::{cmp::Ordering, collections::HashMap, time::Duration};
pub enum BuffKind { pub enum BuffKind {
/// Restores health/time for some period /// Restores health/time for some period
Regeneration, Regeneration,
/// Restores health/time for some period for consumables
Saturation,
/// Lowers health over time for some duration /// Lowers health over time for some duration
Bleeding, Bleeding,
/// Lower a creature's max health /// Lower a creature's max health
/// Currently placeholder buff to show other stuff is possible /// Currently placeholder buff to show other stuff is possible
Cursed, Cursed,
// Applied when drinking a potion
Potion,
} }
impl BuffKind { impl BuffKind {
@ -22,14 +26,16 @@ impl BuffKind {
pub fn is_buff(self) -> bool { pub fn is_buff(self) -> bool {
match self { match self {
BuffKind::Regeneration { .. } => true, BuffKind::Regeneration { .. } => true,
BuffKind::Saturation { .. } => true,
BuffKind::Bleeding { .. } => false, BuffKind::Bleeding { .. } => false,
BuffKind::Cursed { .. } => false, BuffKind::Cursed { .. } => false,
BuffKind::Potion { .. } => true,
} }
} }
} }
// Struct used to store data relevant to a buff // Struct used to store data relevant to a buff
#[derive(Clone, Copy, Debug, Serialize, Deserialize)] #[derive(Clone, Copy, Debug, PartialEq, Serialize, Deserialize)]
pub struct BuffData { pub struct BuffData {
pub strength: f32, pub strength: f32,
pub duration: Option<Duration>, pub duration: Option<Duration>,
@ -121,7 +127,7 @@ impl Buff {
}], }],
data.duration, data.duration,
), ),
BuffKind::Regeneration => ( BuffKind::Regeneration | BuffKind::Saturation | BuffKind::Potion => (
vec![BuffEffect::HealthChangeOverTime { vec![BuffEffect::HealthChangeOverTime {
rate: data.strength, rate: data.strength,
accumulated: 0.0, accumulated: 0.0,

View File

@ -83,7 +83,7 @@ pub enum ItemKind {
Glider(Glider), Glider(Glider),
Consumable { Consumable {
kind: String, kind: String,
effect: Effect, effect: Vec<Effect>,
}, },
Throwable { Throwable {
kind: Throwable, kind: Throwable,
@ -337,6 +337,8 @@ impl Item {
SpriteKind::Stones => "common.items.crafting_ing.stones", SpriteKind::Stones => "common.items.crafting_ing.stones",
SpriteKind::Twigs => "common.items.crafting_ing.twigs", SpriteKind::Twigs => "common.items.crafting_ing.twigs",
SpriteKind::ShinyGem => "common.items.crafting_ing.shiny_gem", SpriteKind::ShinyGem => "common.items.crafting_ing.shiny_gem",
SpriteKind::VialEmpty => "common.items.crafting_ing.empty_vial",
SpriteKind::PotionMinor => "common.items.consumable.potion_minor",
_ => return None, _ => return None,
})) }))
} }

View File

@ -260,8 +260,10 @@ impl Default for Inventory {
slots: vec![None; 36], slots: vec![None; 36],
amount: 0, amount: 0,
}; };
inventory.push(Item::new_from_asset_expect(
"common.items.consumable.potion_minor",
));
inventory.push(Item::new_from_asset_expect("common.items.food.cheese")); inventory.push(Item::new_from_asset_expect("common.items.food.cheese"));
inventory.push(Item::new_from_asset_expect("common.items.food.apple"));
inventory inventory
} }
} }

View File

@ -2,11 +2,20 @@ use crate::{combat, comp};
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
/// An effect that may be applied to an entity /// An effect that may be applied to an entity
#[derive(Copy, Clone, Debug, PartialEq, Serialize, Deserialize)] #[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
pub enum Effect { pub enum Effect {
Health(comp::HealthChange), Health(comp::HealthChange),
Xp(i64), Xp(i64),
Damage(combat::Damage), Damage(combat::Damage),
Buff(BuffEffect),
}
/// A buff that may be applied to an entity
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
pub struct BuffEffect {
pub kind: comp::BuffKind,
pub data: comp::BuffData,
pub cat_ids: Vec<comp::BuffCategory>,
} }
impl Effect { impl Effect {
@ -15,6 +24,7 @@ impl Effect {
Effect::Health(c) => format!("{:+} health", c.amount), Effect::Health(c) => format!("{:+} health", c.amount),
Effect::Xp(n) => format!("{:+} exp", n), Effect::Xp(n) => format!("{:+} exp", n),
Effect::Damage(d) => format!("{:+}", d.value), Effect::Damage(d) => format!("{:+}", d.value),
Effect::Buff(e) => format!("{:?} buff", e),
} }
} }
@ -29,6 +39,9 @@ impl Effect {
Effect::Damage(damage) => { Effect::Damage(damage) => {
damage.interpolate_damage(modifier, 0.0); damage.interpolate_damage(modifier, 0.0);
}, },
Effect::Buff(effect) => {
effect.data.strength *= modifier;
},
} }
} }
} }

View File

@ -102,6 +102,8 @@ make_case_elim!(
Reed = 0x4C, Reed = 0x4C,
Beehive = 0x4D, Beehive = 0x4D,
LargeCactus = 0x4E, LargeCactus = 0x4E,
VialEmpty = 0x4F,
PotionMinor = 0x50,
} }
); );
@ -184,6 +186,8 @@ impl SpriteKind {
SpriteKind::ShinyGem => true, SpriteKind::ShinyGem => true,
SpriteKind::Crate => true, SpriteKind::Crate => true,
SpriteKind::Beehive => true, SpriteKind::Beehive => true,
SpriteKind::VialEmpty => true,
SpriteKind::PotionMinor => true,
_ => false, _ => false,
} }
} }
@ -221,6 +225,8 @@ impl SpriteKind {
| SpriteKind::DropGateBottom | SpriteKind::DropGateBottom
| SpriteKind::Door | SpriteKind::Door
| SpriteKind::Beehive | SpriteKind::Beehive
| SpriteKind::PotionMinor
| SpriteKind::VialEmpty
) )
} }
} }

View File

@ -649,7 +649,7 @@ pub fn handle_explosion(
if is_alive { if is_alive {
effect.modify_strength(strength); effect.modify_strength(strength);
server.state().apply_effect(entity_b, effect, owner); server.state().apply_effect(entity_b, effect.clone(), owner);
// Apply energy change // Apply energy change
if let Some(owner) = owner_entity { if let Some(owner) = owner_entity {
if let Some(energy) = if let Some(energy) =

View File

@ -211,7 +211,7 @@ pub fn handle_inventory(server: &mut Server, entity: EcsEntity, manip: comp::Inv
} else if let Some(item) = inventory.take(slot) { } else if let Some(item) = inventory.take(slot) {
match item.kind() { match item.kind() {
ItemKind::Consumable { kind, effect, .. } => { ItemKind::Consumable { kind, effect, .. } => {
maybe_effect = Some(*effect); maybe_effect = Some(effect.clone());
Some(comp::InventoryUpdateEvent::Consumed(kind.clone())) Some(comp::InventoryUpdateEvent::Consumed(kind.clone()))
}, },
ItemKind::Throwable { kind, .. } => { ItemKind::Throwable { kind, .. } => {
@ -348,8 +348,10 @@ pub fn handle_inventory(server: &mut Server, entity: EcsEntity, manip: comp::Inv
}; };
drop(inventories); drop(inventories);
if let Some(effect) = maybe_effect { if let Some(effects) = maybe_effect {
state.apply_effect(entity, effect, None); for effect in effects {
state.apply_effect(entity, effect, None);
}
} }
if let Some(event) = event { if let Some(event) = event {
state.write_component(entity, comp::InventoryUpdate::new(event)); state.write_component(entity, comp::InventoryUpdate::new(event));

View File

@ -71,8 +71,8 @@ pub trait StateExt {
} }
impl StateExt for State { impl StateExt for State {
fn apply_effect(&self, entity: EcsEntity, effect: Effect, source: Option<Uid>) { fn apply_effect(&self, entity: EcsEntity, effects: Effect, source: Option<Uid>) {
match effect { match effects {
Effect::Health(change) => { Effect::Health(change) => {
self.ecs() self.ecs()
.write_storage::<comp::Health>() .write_storage::<comp::Health>()
@ -93,6 +93,19 @@ impl StateExt for State {
.get_mut(entity) .get_mut(entity)
.map(|health| health.change_by(change)); .map(|health| health.change_by(change));
}, },
Effect::Buff(buff) => {
self.ecs()
.write_storage::<comp::Buffs>()
.get_mut(entity)
.map(|buffs| {
buffs.insert(comp::Buff::new(
buff.kind,
buff.data,
buff.cat_ids,
comp::BuffSource::Item,
))
});
},
} }
} }

View File

@ -138,7 +138,7 @@ impl<'a> System<'a> for Sys {
body, body,
); );
} }
stats.level.set_level(rand::thread_rng().gen_range(30, 35)); stats.level.set_level(rand::thread_rng().gen_range(25, 30));
scale = 2.0 + rand::random::<f32>(); scale = 2.0 + rand::random::<f32>();
} }

View File

@ -182,6 +182,8 @@ impl<'a> Widget for BuffsBar<'a> {
}) as u32; // Percentage to determine which frame of the timer overlay is displayed }) as u32; // Percentage to determine which frame of the timer overlay is displayed
let buff_img = match buff.kind { let buff_img = match buff.kind {
BuffKind::Regeneration { .. } => self.imgs.buff_plus_0, BuffKind::Regeneration { .. } => self.imgs.buff_plus_0,
BuffKind::Saturation { .. } => self.imgs.buff_saturation_0,
BuffKind::Potion { .. } => self.imgs.buff_potion_0,
_ => self.imgs.missing_icon, _ => self.imgs.missing_icon,
}; };
let buff_widget = Image::new(buff_img).w_h(20.0, 20.0); let buff_widget = Image::new(buff_img).w_h(20.0, 20.0);
@ -204,9 +206,11 @@ impl<'a> Widget for BuffsBar<'a> {
.set(id, ui); .set(id, ui);
// Create Buff tooltip // Create Buff tooltip
let title = match buff.kind { let title = match buff.kind {
BuffKind::Regeneration { .. } => { BuffKind::Regeneration { .. } => localized_strings.get("buff.title.heal"),
localized_strings.get("buff.title.heal_test") BuffKind::Saturation { .. } => {
localized_strings.get("buff.title.saturation")
}, },
BuffKind::Potion { .. } => localized_strings.get("buff.title.potion"),
_ => localized_strings.get("buff.title.missing"), _ => localized_strings.get("buff.title.missing"),
}; };
let remaining_time = if current_duration.is_none() { let remaining_time = if current_duration.is_none() {
@ -216,9 +220,11 @@ impl<'a> Widget for BuffsBar<'a> {
}; };
let click_to_remove = format!("<{}>", &localized_strings.get("buff.remove")); let click_to_remove = format!("<{}>", &localized_strings.get("buff.remove"));
let desc_txt = match buff.kind { let desc_txt = match buff.kind {
BuffKind::Regeneration { .. } => { BuffKind::Regeneration { .. } => localized_strings.get("buff.desc.heal"),
localized_strings.get("buff.desc.heal_test") BuffKind::Saturation { .. } => {
localized_strings.get("buff.desc.saturation")
}, },
BuffKind::Potion { .. } => localized_strings.get("buff.desc.potion"),
_ => localized_strings.get("buff.desc.missing"), _ => localized_strings.get("buff.desc.missing"),
}; };
let desc = format!("{}\n\n{}\n\n{}", desc_txt, remaining_time, click_to_remove); let desc = format!("{}\n\n{}\n\n{}", desc_txt, remaining_time, click_to_remove);
@ -296,9 +302,7 @@ impl<'a> Widget for BuffsBar<'a> {
.set(id, ui); .set(id, ui);
// Create Debuff tooltip // Create Debuff tooltip
let title = match debuff.kind { let title = match debuff.kind {
BuffKind::Bleeding { .. } => { BuffKind::Bleeding { .. } => localized_strings.get("debuff.title.bleed"),
localized_strings.get("debuff.title.bleed_test")
},
_ => localized_strings.get("buff.title.missing"), _ => localized_strings.get("buff.title.missing"),
}; };
let remaining_time = if current_duration.is_none() { let remaining_time = if current_duration.is_none() {
@ -307,9 +311,7 @@ impl<'a> Widget for BuffsBar<'a> {
format!("Remaining: {:.0}s", current_duration.unwrap().as_secs_f32()) format!("Remaining: {:.0}s", current_duration.unwrap().as_secs_f32())
}; };
let desc_txt = match debuff.kind { let desc_txt = match debuff.kind {
BuffKind::Bleeding { .. } => { BuffKind::Bleeding { .. } => localized_strings.get("debuff.desc.bleed"),
localized_strings.get("debuff.desc.bleed_test")
},
_ => localized_strings.get("debuff.desc.missing"), _ => localized_strings.get("debuff.desc.missing"),
}; };
let desc = format!("{}\n\n{}", desc_txt, remaining_time); let desc = format!("{}\n\n{}", desc_txt, remaining_time);
@ -379,8 +381,10 @@ impl<'a> Widget for BuffsBar<'a> {
}) as u32; }) as u32;
let buff_img = match buff.kind { let buff_img = match buff.kind {
BuffKind::Regeneration { .. } => self.imgs.buff_plus_0, BuffKind::Regeneration { .. } => self.imgs.buff_plus_0,
BuffKind::Saturation { .. } => self.imgs.buff_saturation_0,
BuffKind::Bleeding { .. } => self.imgs.debuff_bleed_0, BuffKind::Bleeding { .. } => self.imgs.debuff_bleed_0,
BuffKind::Cursed { .. } => self.imgs.debuff_skull_0, BuffKind::Cursed { .. } => self.imgs.debuff_skull_0,
BuffKind::Potion { .. } => self.imgs.buff_potion_0,
}; };
let buff_widget = Image::new(buff_img).w_h(40.0, 40.0); let buff_widget = Image::new(buff_img).w_h(40.0, 40.0);
// Sort buffs into rows of 6 slots // Sort buffs into rows of 6 slots
@ -402,12 +406,12 @@ impl<'a> Widget for BuffsBar<'a> {
.set(id, ui); .set(id, ui);
// Create Buff tooltip // Create Buff tooltip
let title = match buff.kind { let title = match buff.kind {
BuffKind::Regeneration { .. } => { BuffKind::Regeneration { .. } => localized_strings.get("buff.title.heal"),
localized_strings.get("buff.title.heal_test") BuffKind::Saturation { .. } => {
}, localized_strings.get("buff.title.saturation")
BuffKind::Bleeding { .. } => {
localized_strings.get("debuff.title.bleed_test")
}, },
BuffKind::Potion { .. } => localized_strings.get("buff.title.potion"),
BuffKind::Bleeding { .. } => localized_strings.get("debuff.title.bleed"),
_ => localized_strings.get("buff.title.missing"), _ => localized_strings.get("buff.title.missing"),
}; };
let remaining_time = if current_duration.is_none() { let remaining_time = if current_duration.is_none() {
@ -417,12 +421,12 @@ impl<'a> Widget for BuffsBar<'a> {
}; };
let click_to_remove = format!("<{}>", &localized_strings.get("buff.remove")); let click_to_remove = format!("<{}>", &localized_strings.get("buff.remove"));
let desc_txt = match buff.kind { let desc_txt = match buff.kind {
BuffKind::Regeneration { .. } => { BuffKind::Regeneration { .. } => localized_strings.get("buff.desc.heal"),
localized_strings.get("buff.desc.heal_test") BuffKind::Saturation { .. } => {
}, localized_strings.get("buff.desc.saturation")
BuffKind::Bleeding { .. } => {
localized_strings.get("debuff.desc.bleed_test")
}, },
BuffKind::Potion { .. } => localized_strings.get("buff.desc.potion"),
BuffKind::Bleeding { .. } => localized_strings.get("debuff.desc.bleed"),
_ => localized_strings.get("buff.desc.missing"), _ => localized_strings.get("buff.desc.missing"),
}; };
let desc = if buff.is_buff { let desc = if buff.is_buff {

View File

@ -482,8 +482,10 @@ impl<'a> Widget for Group<'a> {
}) as u32; // Percentage to determine which frame of the timer overlay is displayed }) as u32; // Percentage to determine which frame of the timer overlay is displayed
let buff_img = match buff.kind { let buff_img = match buff.kind {
BuffKind::Regeneration { .. } => self.imgs.buff_plus_0, BuffKind::Regeneration { .. } => self.imgs.buff_plus_0,
BuffKind::Saturation { .. } => self.imgs.buff_saturation_0,
BuffKind::Bleeding { .. } => self.imgs.debuff_bleed_0, BuffKind::Bleeding { .. } => self.imgs.debuff_bleed_0,
BuffKind::Cursed { .. } => self.imgs.debuff_skull_0, BuffKind::Cursed { .. } => self.imgs.debuff_skull_0,
BuffKind::Potion { .. } => self.imgs.buff_potion_0,
}; };
let buff_widget = Image::new(buff_img).w_h(15.0, 15.0); let buff_widget = Image::new(buff_img).w_h(15.0, 15.0);
let buff_widget = if let Some(id) = prev_id { let buff_widget = if let Some(id) = prev_id {
@ -510,10 +512,13 @@ impl<'a> Widget for Group<'a> {
// Create Buff tooltip // Create Buff tooltip
let title = match buff.kind { let title = match buff.kind {
BuffKind::Regeneration { .. } => { BuffKind::Regeneration { .. } => {
localized_strings.get("buff.title.heal_test") localized_strings.get("buff.title.heal")
},
BuffKind::Saturation { .. } => {
localized_strings.get("buff.title.saturation")
}, },
BuffKind::Bleeding { .. } => { BuffKind::Bleeding { .. } => {
localized_strings.get("debuff.title.bleed_test") localized_strings.get("debuff.title.bleed")
}, },
_ => localized_strings.get("buff.title.missing"), _ => localized_strings.get("buff.title.missing"),
}; };
@ -527,10 +532,13 @@ impl<'a> Widget for Group<'a> {
}; };
let desc_txt = match buff.kind { let desc_txt = match buff.kind {
BuffKind::Regeneration { .. } => { BuffKind::Regeneration { .. } => {
localized_strings.get("buff.desc.heal_test") localized_strings.get("buff.desc.heal")
},
BuffKind::Saturation { .. } => {
localized_strings.get("buff.desc.saturation")
}, },
BuffKind::Bleeding { .. } => { BuffKind::Bleeding { .. } => {
localized_strings.get("debuff.desc.bleed_test") localized_strings.get("debuff.desc.bleed")
}, },
_ => localized_strings.get("buff.desc.missing"), _ => localized_strings.get("buff.desc.missing"),
}; };

View File

@ -352,6 +352,8 @@ image_ids! {
// Buffs // Buffs
buff_plus_0: "voxygen.element.icons.de_buffs.buff_plus_0", buff_plus_0: "voxygen.element.icons.de_buffs.buff_plus_0",
buff_saturation_0: "voxygen.element.icons.de_buffs.buff_saturation_0",
buff_potion_0: "voxygen.element.icons.de_buffs.buff_potion_0",
// Debuffs // Debuffs
debuff_skull_0: "voxygen.element.icons.de_buffs.debuff_skull_0", debuff_skull_0: "voxygen.element.icons.de_buffs.debuff_skull_0",

View File

@ -243,8 +243,10 @@ impl<'a> Widget for Overhead<'a> {
}) as u32; // Percentage to determine which frame of the timer overlay is displayed }) as u32; // Percentage to determine which frame of the timer overlay is displayed
let buff_img = match buff.kind { let buff_img = match buff.kind {
BuffKind::Regeneration { .. } => self.imgs.buff_plus_0, BuffKind::Regeneration { .. } => self.imgs.buff_plus_0,
BuffKind::Saturation { .. } => self.imgs.buff_saturation_0,
BuffKind::Bleeding { .. } => self.imgs.debuff_bleed_0, BuffKind::Bleeding { .. } => self.imgs.debuff_bleed_0,
BuffKind::Cursed { .. } => self.imgs.debuff_skull_0, BuffKind::Cursed { .. } => self.imgs.debuff_skull_0,
BuffKind::Potion { .. } => self.imgs.buff_potion_0,
}; };
let buff_widget = Image::new(buff_img).w_h(20.0, 20.0); let buff_widget = Image::new(buff_img).w_h(20.0, 20.0);
// Sort buffs into rows of 5 slots // Sort buffs into rows of 5 slots

View File

@ -537,7 +537,7 @@ impl Archetype for House {
center_offset.x, center_offset.x,
center_offset.y, center_offset.y,
z + 100, z + 100,
)) % 11 )) % 12
{ {
0 => SpriteKind::Planter, 0 => SpriteKind::Planter,
1 => SpriteKind::ChairSingle, 1 => SpriteKind::ChairSingle,
@ -554,6 +554,13 @@ impl Archetype for House {
7 => SpriteKind::DrawerSmall, 7 => SpriteKind::DrawerSmall,
8 => SpriteKind::TableSide, 8 => SpriteKind::TableSide,
9 => SpriteKind::WardrobeSingle, 9 => SpriteKind::WardrobeSingle,
10 => {
if dynamic_rng.gen_range(0, 10) == 0 {
SpriteKind::PotionMinor
} else {
SpriteKind::VialEmpty
}
},
_ => SpriteKind::Pot, _ => SpriteKind::Pot,
}; };