mirror of
https://gitlab.com/veloren/veloren.git
synced 2024-08-30 18:12:32 +00:00
Merge branch 'isse/small-fixes' into 'master'
Small fixes See merge request veloren/veloren!3846
This commit is contained in:
commit
08ca360926
@ -0,0 +1,24 @@
|
||||
#![enable(implicit_some)]
|
||||
(
|
||||
name: Name("Trickster"),
|
||||
body: RandomWith("draugr"),
|
||||
alignment: Alignment(Enemy),
|
||||
loot: LootTable("common.loot_tables.calendar.april_fools.trickster"),
|
||||
inventory: (
|
||||
loadout: Inline((
|
||||
inherit: Asset("common.loadout.calendar.halloween.trickster"),
|
||||
active_hands: InHands((Choice([
|
||||
(1, Item("common.items.tool.instruments.double_bass")),
|
||||
(1, Item("common.items.tool.instruments.flute")),
|
||||
(1, Item("common.items.tool.instruments.lyre")),
|
||||
(1, Item("common.items.tool.instruments.kalimba")),
|
||||
(1, Item("common.items.tool.instruments.sitar")),
|
||||
(1, Item("common.items.tool.instruments.washboard")),
|
||||
(1, Item("common.items.tool.instruments.lute")),
|
||||
(1, Item("common.items.tool.instruments.guitar")),
|
||||
(1, Item("common.items.tool.instruments.melodica")),
|
||||
]), None)),
|
||||
)),
|
||||
),
|
||||
meta: [],
|
||||
)
|
@ -3,7 +3,7 @@ ItemDef(
|
||||
description: "A potent healing potion.",
|
||||
kind: Consumable(
|
||||
kind: Drink,
|
||||
effects: [
|
||||
effects: All([
|
||||
Buff((
|
||||
kind: Potion,
|
||||
data: (
|
||||
@ -21,7 +21,7 @@ ItemDef(
|
||||
),
|
||||
cat_ids: [Natural],
|
||||
)),
|
||||
]
|
||||
])
|
||||
),
|
||||
quality: High,
|
||||
tags: [Potion],
|
||||
|
67
assets/common/items/consumable/curious_potion.ron
Normal file
67
assets/common/items/consumable/curious_potion.ron
Normal file
@ -0,0 +1,67 @@
|
||||
ItemDef(
|
||||
name: "Curious Potion",
|
||||
description: "Wonder what this does...",
|
||||
kind: Consumable(
|
||||
kind: Drink,
|
||||
effects: Any([
|
||||
Buff((
|
||||
kind: Polymorphed(QuadrupedSmall(( species: Frog, body_type: Female ))),
|
||||
data: (
|
||||
strength: 0.0,
|
||||
duration: Some(60),
|
||||
),
|
||||
cat_ids: [Natural],
|
||||
)),
|
||||
Buff((
|
||||
kind: Polymorphed(QuadrupedSmall(( species: Rabbit, body_type: Female ))),
|
||||
data: (
|
||||
strength: 0.0,
|
||||
duration: Some(60),
|
||||
),
|
||||
cat_ids: [Natural],
|
||||
)),
|
||||
Buff((
|
||||
kind: Polymorphed(QuadrupedSmall(( species: Rat, body_type: Female ))),
|
||||
data: (
|
||||
strength: 0.0,
|
||||
duration: Some(60),
|
||||
),
|
||||
cat_ids: [Natural],
|
||||
)),
|
||||
Buff((
|
||||
kind: Polymorphed(QuadrupedSmall(( species: Squirrel, body_type: Female ))),
|
||||
data: (
|
||||
strength: 0.0,
|
||||
duration: Some(60),
|
||||
),
|
||||
cat_ids: [Natural],
|
||||
)),
|
||||
Buff((
|
||||
kind: Polymorphed(QuadrupedSmall(( species: Cat, body_type: Female ))),
|
||||
data: (
|
||||
strength: 0.0,
|
||||
duration: Some(60),
|
||||
),
|
||||
cat_ids: [Natural],
|
||||
)),
|
||||
Buff((
|
||||
kind: Polymorphed(QuadrupedSmall(( species: Fungome, body_type: Female ))),
|
||||
data: (
|
||||
strength: 0.0,
|
||||
duration: Some(60),
|
||||
),
|
||||
cat_ids: [Natural],
|
||||
)),
|
||||
Buff((
|
||||
kind: Polymorphed(QuadrupedSmall(( species: Pig, body_type: Female ))),
|
||||
data: (
|
||||
strength: 0.0,
|
||||
duration: Some(60),
|
||||
),
|
||||
cat_ids: [Natural],
|
||||
)),
|
||||
])
|
||||
),
|
||||
quality: Common,
|
||||
tags: [Potion],
|
||||
)
|
@ -3,7 +3,7 @@ ItemDef(
|
||||
description: "Precious medicine, it makes for the largest rejuvenative flask yet.",
|
||||
kind: Consumable(
|
||||
kind: Drink,
|
||||
effects: [
|
||||
effects: All([
|
||||
Buff((
|
||||
kind: Potion,
|
||||
data: (
|
||||
@ -20,7 +20,7 @@ ItemDef(
|
||||
),
|
||||
cat_ids: [Natural],
|
||||
)),
|
||||
]
|
||||
])
|
||||
),
|
||||
quality: Common,
|
||||
tags: [Potion],
|
||||
|
@ -3,7 +3,7 @@ ItemDef(
|
||||
description: "An innovative invention from an apothecary, better than its smaller precursors.",
|
||||
kind: Consumable(
|
||||
kind: Drink,
|
||||
effects: [
|
||||
effects: All([
|
||||
Buff((
|
||||
kind: Potion,
|
||||
data: (
|
||||
@ -20,7 +20,7 @@ ItemDef(
|
||||
),
|
||||
cat_ids: [Natural],
|
||||
)),
|
||||
]
|
||||
])
|
||||
),
|
||||
quality: Common,
|
||||
tags: [Potion],
|
||||
|
@ -3,7 +3,7 @@ ItemDef(
|
||||
description: "A small potion concocted from apples and honey.",
|
||||
kind: Consumable(
|
||||
kind: Drink,
|
||||
effects: [
|
||||
effects: All([
|
||||
Buff((
|
||||
kind: Potion,
|
||||
data: (
|
||||
@ -20,7 +20,7 @@ ItemDef(
|
||||
),
|
||||
cat_ids: [Natural],
|
||||
)),
|
||||
]
|
||||
])
|
||||
),
|
||||
quality: Common,
|
||||
tags: [Potion],
|
||||
|
@ -3,7 +3,7 @@ ItemDef(
|
||||
description: "They say gods eat it to get eternal youth.",
|
||||
kind: Consumable(
|
||||
kind: Drink,
|
||||
effects: [
|
||||
effects: All([
|
||||
Buff((
|
||||
kind: Regeneration,
|
||||
data: (
|
||||
@ -36,7 +36,7 @@ ItemDef(
|
||||
),
|
||||
cat_ids: [Natural],
|
||||
)),
|
||||
]
|
||||
])
|
||||
),
|
||||
quality: Debug,
|
||||
tags: [Food],
|
||||
|
@ -3,7 +3,7 @@ ItemDef(
|
||||
description: "Red and juicy",
|
||||
kind: Consumable(
|
||||
kind: Food,
|
||||
effects: [
|
||||
effects: One(
|
||||
Buff((
|
||||
kind: Saturation,
|
||||
data: (
|
||||
@ -12,7 +12,7 @@ ItemDef(
|
||||
),
|
||||
cat_ids: [Natural],
|
||||
)),
|
||||
]
|
||||
)
|
||||
),
|
||||
quality: Common,
|
||||
tags: [Food],
|
||||
|
@ -3,7 +3,7 @@ ItemDef(
|
||||
description: "Who could say no to that?",
|
||||
kind: Consumable(
|
||||
kind: ComplexFood,
|
||||
effects: [
|
||||
effects: All([
|
||||
Buff((
|
||||
kind: Saturation,
|
||||
data: (
|
||||
@ -20,7 +20,7 @@ ItemDef(
|
||||
),
|
||||
cat_ids: [Natural],
|
||||
)),
|
||||
]
|
||||
])
|
||||
),
|
||||
quality: Moderate,
|
||||
tags: [Food],
|
||||
|
@ -3,7 +3,7 @@ ItemDef(
|
||||
description: "The stick makes it easier to carry!",
|
||||
kind: Consumable(
|
||||
kind: Food,
|
||||
effects: [
|
||||
effects: One(
|
||||
Buff((
|
||||
kind: Saturation,
|
||||
data: (
|
||||
@ -12,7 +12,7 @@ ItemDef(
|
||||
),
|
||||
cat_ids: [Natural],
|
||||
)),
|
||||
]
|
||||
)
|
||||
),
|
||||
quality: Common,
|
||||
tags: [Food],
|
||||
|
@ -3,7 +3,7 @@ ItemDef(
|
||||
description: "Pungent and filling",
|
||||
kind: Consumable(
|
||||
kind: Food,
|
||||
effects: [
|
||||
effects: One(
|
||||
Buff((
|
||||
kind: Saturation,
|
||||
data: (
|
||||
@ -12,7 +12,7 @@ ItemDef(
|
||||
),
|
||||
cat_ids: [Natural],
|
||||
)),
|
||||
]
|
||||
)
|
||||
),
|
||||
quality: High,
|
||||
tags: [Food],
|
||||
|
@ -3,7 +3,7 @@ ItemDef(
|
||||
description: "Giving you that special prickle.",
|
||||
kind: Consumable(
|
||||
kind: Drink,
|
||||
effects: [
|
||||
effects: One(
|
||||
Buff((
|
||||
kind: Saturation,
|
||||
data: (
|
||||
@ -12,7 +12,7 @@ ItemDef(
|
||||
),
|
||||
cat_ids: [Natural],
|
||||
)),
|
||||
]
|
||||
)
|
||||
),
|
||||
quality: Moderate,
|
||||
tags: [Food],
|
||||
|
@ -3,7 +3,7 @@ ItemDef(
|
||||
description: "An orange root vegetable. They say it'll improve your vision!",
|
||||
kind: Consumable(
|
||||
kind: Food,
|
||||
effects: [
|
||||
effects: One(
|
||||
Buff((
|
||||
kind: Saturation,
|
||||
data: (
|
||||
@ -12,7 +12,7 @@ ItemDef(
|
||||
),
|
||||
cat_ids: [Natural],
|
||||
)),
|
||||
]
|
||||
)
|
||||
),
|
||||
quality: Common,
|
||||
tags: [Food],
|
||||
|
@ -3,7 +3,7 @@ ItemDef(
|
||||
description: "Made from goat milk from the finest dwarven produce. Aromatic and nutritious!",
|
||||
kind: Consumable(
|
||||
kind: Food,
|
||||
effects: [
|
||||
effects: One(
|
||||
Buff((
|
||||
kind: Saturation,
|
||||
data: (
|
||||
@ -12,7 +12,7 @@ ItemDef(
|
||||
),
|
||||
cat_ids: [Natural],
|
||||
)),
|
||||
]
|
||||
)
|
||||
),
|
||||
quality: Common,
|
||||
tags: [Food],
|
||||
|
@ -3,7 +3,7 @@ ItemDef(
|
||||
description: "Reliable source of water and fat. Can often be found growing on palm trees.",
|
||||
kind: Consumable(
|
||||
kind: Food,
|
||||
effects: [
|
||||
effects: One(
|
||||
Buff((
|
||||
kind: Saturation,
|
||||
data: (
|
||||
@ -12,7 +12,7 @@ ItemDef(
|
||||
),
|
||||
cat_ids: [Natural],
|
||||
)),
|
||||
]
|
||||
)
|
||||
),
|
||||
quality: Common,
|
||||
tags: [Food],
|
||||
|
@ -3,7 +3,7 @@ ItemDef(
|
||||
description: "A daisy-like flower often used in herbal teas.",
|
||||
kind: Consumable(
|
||||
kind: Food,
|
||||
effects: [
|
||||
effects: One(
|
||||
Buff((
|
||||
kind: Saturation,
|
||||
data: (
|
||||
@ -12,7 +12,7 @@ ItemDef(
|
||||
),
|
||||
cat_ids: [Natural],
|
||||
)),
|
||||
]
|
||||
)
|
||||
),
|
||||
quality: Common,
|
||||
tags: [Food],
|
||||
|
@ -3,7 +3,7 @@ ItemDef(
|
||||
description: "A small, yellow flower. Uses the wind to spread its seeds.",
|
||||
kind: Consumable(
|
||||
kind: Food,
|
||||
effects: [
|
||||
effects: One(
|
||||
Buff((
|
||||
kind: Saturation,
|
||||
data: (
|
||||
@ -12,7 +12,7 @@ ItemDef(
|
||||
),
|
||||
cat_ids: [Natural],
|
||||
)),
|
||||
]
|
||||
)
|
||||
),
|
||||
quality: Common,
|
||||
tags: [Food],
|
||||
|
@ -3,7 +3,7 @@ ItemDef(
|
||||
description: "Make sure to brush your teeth after eating.",
|
||||
kind: Consumable(
|
||||
kind: Food,
|
||||
effects: [
|
||||
effects: One(
|
||||
Buff((
|
||||
kind: Saturation,
|
||||
data: (
|
||||
@ -12,7 +12,7 @@ ItemDef(
|
||||
),
|
||||
cat_ids: [Natural],
|
||||
)),
|
||||
]
|
||||
)
|
||||
),
|
||||
quality: Common,
|
||||
tags: [Food],
|
||||
|
@ -3,7 +3,7 @@ ItemDef(
|
||||
description: "Sweeet",
|
||||
kind: Consumable(
|
||||
kind: Food,
|
||||
effects: [
|
||||
effects: One(
|
||||
Buff((
|
||||
kind: Saturation,
|
||||
data: (
|
||||
@ -12,7 +12,7 @@ ItemDef(
|
||||
),
|
||||
cat_ids: [Natural],
|
||||
)),
|
||||
]
|
||||
)
|
||||
),
|
||||
quality: Common,
|
||||
tags: [Food],
|
||||
|
@ -3,7 +3,7 @@ ItemDef(
|
||||
description: "A vibrant green leafy vegetable. Lettuce make some salads!",
|
||||
kind: Consumable(
|
||||
kind: Food,
|
||||
effects: [
|
||||
effects: One(
|
||||
Buff((
|
||||
kind: Saturation,
|
||||
data: (
|
||||
@ -12,7 +12,7 @@ ItemDef(
|
||||
),
|
||||
cat_ids: [Natural],
|
||||
)),
|
||||
]
|
||||
)
|
||||
),
|
||||
quality: Common,
|
||||
tags: [Food],
|
||||
|
@ -3,7 +3,7 @@ ItemDef(
|
||||
description: "Meat. The lifeblood of mankind.",
|
||||
kind: Consumable(
|
||||
kind: Food,
|
||||
effects: [
|
||||
effects: One(
|
||||
Buff((
|
||||
kind: Saturation,
|
||||
data: (
|
||||
@ -12,7 +12,7 @@ ItemDef(
|
||||
),
|
||||
cat_ids: [Natural],
|
||||
)),
|
||||
]
|
||||
)
|
||||
),
|
||||
quality: Common,
|
||||
tags: [Food],
|
||||
|
@ -3,7 +3,7 @@ ItemDef(
|
||||
description: "Medium Rare.",
|
||||
kind: Consumable(
|
||||
kind: Food,
|
||||
effects: [
|
||||
effects: One(
|
||||
Buff((
|
||||
kind: Saturation,
|
||||
data: (
|
||||
@ -12,7 +12,7 @@ ItemDef(
|
||||
),
|
||||
cat_ids: [Natural],
|
||||
)),
|
||||
]
|
||||
)
|
||||
),
|
||||
quality: Common,
|
||||
tags: [Food],
|
||||
|
@ -3,7 +3,7 @@ ItemDef(
|
||||
description: "Chunk of beastly animal meat, best after cooking.",
|
||||
kind: Consumable(
|
||||
kind: Food,
|
||||
effects: [
|
||||
effects: One(
|
||||
Buff((
|
||||
kind: Saturation,
|
||||
data: (
|
||||
@ -12,7 +12,7 @@ ItemDef(
|
||||
),
|
||||
cat_ids: [Natural],
|
||||
)),
|
||||
]
|
||||
)
|
||||
),
|
||||
quality: Common,
|
||||
tags: [Food],
|
||||
|
@ -3,7 +3,7 @@ ItemDef(
|
||||
description: "Medium Rare.",
|
||||
kind: Consumable(
|
||||
kind: Food,
|
||||
effects: [
|
||||
effects: One(
|
||||
Buff((
|
||||
kind: Saturation,
|
||||
data: (
|
||||
@ -12,7 +12,7 @@ ItemDef(
|
||||
),
|
||||
cat_ids: [Natural],
|
||||
)),
|
||||
]
|
||||
)
|
||||
),
|
||||
quality: Common,
|
||||
tags: [Food],
|
||||
|
@ -3,7 +3,7 @@ ItemDef(
|
||||
description: "Small hunk of beastly animal meat, best after cooking.",
|
||||
kind: Consumable(
|
||||
kind: Food,
|
||||
effects: [
|
||||
effects: One(
|
||||
Buff((
|
||||
kind: Saturation,
|
||||
data: (
|
||||
@ -12,7 +12,7 @@ ItemDef(
|
||||
),
|
||||
cat_ids: [Natural],
|
||||
)),
|
||||
]
|
||||
)
|
||||
),
|
||||
quality: Common,
|
||||
tags: [Food],
|
||||
|
@ -3,7 +3,7 @@ ItemDef(
|
||||
description: "Best enjoyed with one in each hand.",
|
||||
kind: Consumable(
|
||||
kind: Food,
|
||||
effects: [
|
||||
effects: One(
|
||||
Buff((
|
||||
kind: Saturation,
|
||||
data: (
|
||||
@ -12,7 +12,7 @@ ItemDef(
|
||||
),
|
||||
cat_ids: [Natural],
|
||||
)),
|
||||
]
|
||||
)
|
||||
),
|
||||
quality: Common,
|
||||
tags: [Food],
|
||||
|
@ -3,7 +3,7 @@ ItemDef(
|
||||
description: "Makes for a legendary meal.",
|
||||
kind: Consumable(
|
||||
kind: Food,
|
||||
effects: [
|
||||
effects: One(
|
||||
Buff((
|
||||
kind: Saturation,
|
||||
data: (
|
||||
@ -12,7 +12,7 @@ ItemDef(
|
||||
),
|
||||
cat_ids: [Natural],
|
||||
)),
|
||||
]
|
||||
)
|
||||
),
|
||||
quality: Common,
|
||||
tags: [Food],
|
||||
|
@ -3,7 +3,7 @@ ItemDef(
|
||||
description: "It's magnificent.",
|
||||
kind: Consumable(
|
||||
kind: Food,
|
||||
effects: [
|
||||
effects: One(
|
||||
Buff((
|
||||
kind: Saturation,
|
||||
data: (
|
||||
@ -12,7 +12,7 @@ ItemDef(
|
||||
),
|
||||
cat_ids: [Natural],
|
||||
)),
|
||||
]
|
||||
)
|
||||
),
|
||||
quality: Common,
|
||||
tags: [Food],
|
||||
|
@ -3,7 +3,7 @@ ItemDef(
|
||||
description: "A hefty drumstick.",
|
||||
kind: Consumable(
|
||||
kind: Food,
|
||||
effects: [
|
||||
effects: One(
|
||||
Buff((
|
||||
kind: Saturation,
|
||||
data: (
|
||||
@ -12,7 +12,7 @@ ItemDef(
|
||||
),
|
||||
cat_ids: [Natural],
|
||||
)),
|
||||
]
|
||||
)
|
||||
),
|
||||
quality: Common,
|
||||
tags: [Food],
|
||||
|
@ -3,7 +3,7 @@ ItemDef(
|
||||
description: "A fresh cooked seafood steak.",
|
||||
kind: Consumable(
|
||||
kind: Food,
|
||||
effects: [
|
||||
effects: One(
|
||||
Buff((
|
||||
kind: Saturation,
|
||||
data: (
|
||||
@ -12,7 +12,7 @@ ItemDef(
|
||||
),
|
||||
cat_ids: [Natural],
|
||||
)),
|
||||
]
|
||||
)
|
||||
),
|
||||
quality: Common,
|
||||
tags: [Food],
|
||||
|
@ -3,7 +3,7 @@ ItemDef(
|
||||
description: "A steak chopped from a fish, best after cooking.",
|
||||
kind: Consumable(
|
||||
kind: Food,
|
||||
effects: [
|
||||
effects: One(
|
||||
Buff((
|
||||
kind: Saturation,
|
||||
data: (
|
||||
@ -12,7 +12,7 @@ ItemDef(
|
||||
),
|
||||
cat_ids: [Natural],
|
||||
)),
|
||||
]
|
||||
)
|
||||
),
|
||||
quality: Common,
|
||||
tags: [Food],
|
||||
|
@ -3,7 +3,7 @@ ItemDef(
|
||||
description: "Tastes exotic.",
|
||||
kind: Consumable(
|
||||
kind: Food,
|
||||
effects: [
|
||||
effects: One(
|
||||
Buff((
|
||||
kind: Saturation,
|
||||
data: (
|
||||
@ -12,7 +12,7 @@ ItemDef(
|
||||
),
|
||||
cat_ids: [Natural],
|
||||
)),
|
||||
]
|
||||
)
|
||||
),
|
||||
quality: Common,
|
||||
tags: [Food],
|
||||
|
@ -3,7 +3,7 @@ ItemDef(
|
||||
description: "Peculiar bit of meat, best after cooking.",
|
||||
kind: Consumable(
|
||||
kind: Food,
|
||||
effects: [
|
||||
effects: One(
|
||||
Buff((
|
||||
kind: Saturation,
|
||||
data: (
|
||||
@ -12,7 +12,7 @@ ItemDef(
|
||||
),
|
||||
cat_ids: [Natural],
|
||||
)),
|
||||
]
|
||||
)
|
||||
),
|
||||
quality: Common,
|
||||
tags: [Food],
|
||||
|
@ -3,7 +3,7 @@ ItemDef(
|
||||
description: "Hopefully this one is not poisonous",
|
||||
kind: Consumable(
|
||||
kind: Food,
|
||||
effects: [
|
||||
effects: One(
|
||||
Buff((
|
||||
kind: Saturation,
|
||||
data: (
|
||||
@ -12,7 +12,7 @@ ItemDef(
|
||||
),
|
||||
cat_ids: [Natural],
|
||||
)),
|
||||
]
|
||||
)
|
||||
),
|
||||
quality: Common,
|
||||
tags: [Food],
|
||||
|
@ -3,7 +3,7 @@ ItemDef(
|
||||
description: "Roasted mushrooms on a stick for easy carrying",
|
||||
kind: Consumable(
|
||||
kind: Food,
|
||||
effects: [
|
||||
effects: One(
|
||||
Buff((
|
||||
kind: Saturation,
|
||||
data: (
|
||||
@ -12,7 +12,7 @@ ItemDef(
|
||||
),
|
||||
cat_ids: [Natural],
|
||||
)),
|
||||
]
|
||||
)
|
||||
),
|
||||
quality: Common,
|
||||
tags: [Food],
|
||||
|
@ -3,7 +3,7 @@ ItemDef(
|
||||
description: "A vegetable that's made the toughest men cry.",
|
||||
kind: Consumable(
|
||||
kind: Food,
|
||||
effects: [
|
||||
effects: One(
|
||||
Buff((
|
||||
kind: Saturation,
|
||||
data: (
|
||||
@ -12,7 +12,7 @@ ItemDef(
|
||||
),
|
||||
cat_ids: [Natural],
|
||||
)),
|
||||
]
|
||||
)
|
||||
),
|
||||
quality: Common,
|
||||
tags: [Food],
|
||||
|
@ -3,7 +3,7 @@ ItemDef(
|
||||
description: "Literally just chopped lettuce. Does this even count as a salad?",
|
||||
kind: Consumable(
|
||||
kind: Food,
|
||||
effects: [
|
||||
effects: One(
|
||||
Buff((
|
||||
kind: Saturation,
|
||||
data: (
|
||||
@ -12,7 +12,7 @@ ItemDef(
|
||||
),
|
||||
cat_ids: [Natural],
|
||||
)),
|
||||
]
|
||||
)
|
||||
),
|
||||
quality: Common,
|
||||
tags: [Food],
|
||||
|
@ -3,7 +3,7 @@ ItemDef(
|
||||
description: "Brewed from moldy pumpkins.",
|
||||
kind: Consumable(
|
||||
kind: Drink,
|
||||
effects: [
|
||||
effects: One(
|
||||
Buff((
|
||||
kind: Saturation,
|
||||
data: (
|
||||
@ -12,7 +12,7 @@ ItemDef(
|
||||
),
|
||||
cat_ids: [Natural],
|
||||
)),
|
||||
]
|
||||
)
|
||||
),
|
||||
quality: Moderate,
|
||||
tags: [Food],
|
||||
|
@ -3,7 +3,7 @@ ItemDef(
|
||||
description: "A herb commonly used in tea.",
|
||||
kind: Consumable(
|
||||
kind: Food,
|
||||
effects: [
|
||||
effects: One(
|
||||
Buff((
|
||||
kind: Saturation,
|
||||
data: (
|
||||
@ -12,7 +12,7 @@ ItemDef(
|
||||
),
|
||||
cat_ids: [Natural],
|
||||
)),
|
||||
]
|
||||
)
|
||||
),
|
||||
quality: Common,
|
||||
tags: [Food],
|
||||
|
@ -3,7 +3,7 @@ ItemDef(
|
||||
description: "You feel an evil force pulsating within.\n\nIt may be unwise to hold on to it for too long...",
|
||||
kind: Consumable(
|
||||
kind: ComplexFood,
|
||||
effects: [
|
||||
effects: All([
|
||||
Buff((
|
||||
kind: Frenzied,
|
||||
data: (
|
||||
@ -20,7 +20,7 @@ ItemDef(
|
||||
),
|
||||
cat_ids: [Natural],
|
||||
)),
|
||||
]
|
||||
])
|
||||
),
|
||||
quality: Epic,
|
||||
tags: [Food],
|
||||
|
@ -3,7 +3,7 @@ ItemDef(
|
||||
description: "Brewed from freshly shelled sunflower seeds",
|
||||
kind: Consumable(
|
||||
kind: Drink,
|
||||
effects: [
|
||||
effects: One(
|
||||
Buff((
|
||||
kind: Saturation,
|
||||
data: (
|
||||
@ -12,7 +12,7 @@ ItemDef(
|
||||
),
|
||||
cat_ids: [Natural],
|
||||
)),
|
||||
]
|
||||
)
|
||||
),
|
||||
quality: Moderate,
|
||||
tags: [Food],
|
||||
|
@ -3,7 +3,7 @@ ItemDef(
|
||||
description: "A red fruit. It's not actually a vegetable!",
|
||||
kind: Consumable(
|
||||
kind: Food,
|
||||
effects: [
|
||||
effects: One(
|
||||
Buff((
|
||||
kind: Saturation,
|
||||
data: (
|
||||
@ -12,7 +12,7 @@ ItemDef(
|
||||
),
|
||||
cat_ids: [Natural],
|
||||
)),
|
||||
]
|
||||
)
|
||||
),
|
||||
quality: Common,
|
||||
tags: [Food],
|
||||
|
@ -3,7 +3,7 @@ ItemDef(
|
||||
description: "Leafy salad with some chopped, juicy tomatoes mixed in.",
|
||||
kind: Consumable(
|
||||
kind: Food,
|
||||
effects: [
|
||||
effects: One(
|
||||
Buff((
|
||||
kind: Saturation,
|
||||
data: (
|
||||
@ -12,7 +12,7 @@ ItemDef(
|
||||
),
|
||||
cat_ids: [Natural],
|
||||
)),
|
||||
]
|
||||
)
|
||||
),
|
||||
quality: Common,
|
||||
tags: [Food],
|
||||
|
@ -0,0 +1,4 @@
|
||||
[
|
||||
(1.0, Item("common.items.consumable.curious_potion")),
|
||||
(19.0, Nothing),
|
||||
]
|
BIN
assets/voxygen/element/de_buffs/debuff_polymorphed.png
(Stored with Git LFS)
Normal file
BIN
assets/voxygen/element/de_buffs/debuff_polymorphed.png
(Stored with Git LFS)
Normal file
Binary file not shown.
@ -76,7 +76,11 @@ buff-stat-potionsickness =
|
||||
## Reckless
|
||||
buff-title-reckless = Reckless
|
||||
buff-desc-reckless = Your attacks are more powerful, however you are leaving your defenses open.
|
||||
## Polymorped
|
||||
buff-title-polymorphed = Polymorphed
|
||||
buff-desc-polymorphed = Your body changes form.
|
||||
## Util
|
||||
buff-text-over_seconds = over { $dur_secs } seconds
|
||||
buff-text-for_seconds = for { $dur_secs } seconds
|
||||
buff-mysterious = Mysterious effect
|
||||
buff-remove = Click to remove
|
||||
|
@ -3134,6 +3134,10 @@
|
||||
"voxel.object.potion_red",
|
||||
(0.0, 0.0, 0.0), (-50.0, 30.0, 20.0), 0.9,
|
||||
),
|
||||
Simple("common.items.consumable.curious_potion"): VoxTrans(
|
||||
"voxel.object.curious_potion",
|
||||
(0.0, 0.0, 0.0), (-50.0, 30.0, 20.0), 0.7,
|
||||
),
|
||||
Simple("common.items.food.cheese"): VoxTrans(
|
||||
"voxel.object.cheese",
|
||||
(0.0, 0.0, 0.0), (-60.0, 27.0, 17.0), 0.7,
|
||||
|
@ -794,6 +794,7 @@
|
||||
Simple("common.items.consumable.potion_med"): "voxel.object.potion_red",
|
||||
Simple("common.items.consumable.potion_minor"): "voxel.object.potion_red",
|
||||
Simple("common.items.consumable.potion_big"): "voxel.object.potion_red",
|
||||
Simple("common.items.consumable.curious_potion"): "voxel.object.curious_potion",
|
||||
Simple("common.items.boss_drops.potions"): "voxel.object.potion_red",
|
||||
Simple("common.items.food.cheese"): "voxel.object.cheese",
|
||||
Simple("common.items.food.blue_cheese"): "voxel.object.blue_cheese",
|
||||
|
BIN
assets/voxygen/voxel/object/curious_potion.vox
(Stored with Git LFS)
Normal file
BIN
assets/voxygen/voxel/object/curious_potion.vox
(Stored with Git LFS)
Normal file
Binary file not shown.
@ -0,0 +1,14 @@
|
||||
SpawnEntry (
|
||||
name: "April Fools Jungle Area",
|
||||
note: "April Fools NPCs",
|
||||
rules: [
|
||||
Pack(
|
||||
groups: [
|
||||
(3, (3, 6, "common.entity.calendar.april_fools.aggressive.trickster")),
|
||||
],
|
||||
spawn_mode: Land,
|
||||
calendar_events: Some([AprilFools]),
|
||||
day_period: [Night, Morning, Noon, Evening],
|
||||
),
|
||||
],
|
||||
)
|
@ -0,0 +1,14 @@
|
||||
SpawnEntry (
|
||||
name: "April Fools Jungle Core",
|
||||
note: "April Fools NPCs",
|
||||
rules: [
|
||||
Pack(
|
||||
groups: [
|
||||
(3, (3, 6, "common.entity.calendar.april_fools.aggressive.trickster")),
|
||||
],
|
||||
spawn_mode: Land,
|
||||
calendar_events: Some([AprilFools]),
|
||||
day_period: [Night, Morning, Noon, Evening],
|
||||
),
|
||||
],
|
||||
)
|
@ -0,0 +1,14 @@
|
||||
SpawnEntry (
|
||||
name: "April Fools Temperate Rainforest",
|
||||
note: "April Fools NPCs",
|
||||
rules: [
|
||||
Pack(
|
||||
groups: [
|
||||
(3, (3, 6, "common.entity.calendar.april_fools.aggressive.trickster")),
|
||||
],
|
||||
spawn_mode: Land,
|
||||
calendar_events: Some([AprilFools]),
|
||||
day_period: [Night, Morning, Noon, Evening],
|
||||
),
|
||||
],
|
||||
)
|
@ -0,0 +1,14 @@
|
||||
SpawnEntry (
|
||||
name: "April Fools Tropical Rainforest",
|
||||
note: "April Fools NPCs",
|
||||
rules: [
|
||||
Pack(
|
||||
groups: [
|
||||
(3, (3, 6, "common.entity.calendar.april_fools.aggressive.trickster")),
|
||||
],
|
||||
spawn_mode: Land,
|
||||
calendar_events: Some([AprilFools]),
|
||||
day_period: [Night, Morning, Noon, Evening],
|
||||
),
|
||||
],
|
||||
)
|
@ -0,0 +1,14 @@
|
||||
SpawnEntry (
|
||||
name: "April Fools Tundra Core",
|
||||
note: "April Fools NPCs",
|
||||
rules: [
|
||||
Pack(
|
||||
groups: [
|
||||
(3, (3, 6, "common.entity.calendar.april_fools.aggressive.trickster")),
|
||||
],
|
||||
spawn_mode: Land,
|
||||
calendar_events: Some([AprilFools]),
|
||||
day_period: [Night, Morning, Noon, Evening],
|
||||
),
|
||||
],
|
||||
)
|
@ -0,0 +1,14 @@
|
||||
SpawnEntry (
|
||||
name: "April Fools Tundra Forest",
|
||||
note: "April Fools NPCs",
|
||||
rules: [
|
||||
Pack(
|
||||
groups: [
|
||||
(3, (3, 6, "common.entity.calendar.april_fools.aggressive.trickster")),
|
||||
],
|
||||
spawn_mode: Land,
|
||||
calendar_events: Some([AprilFools]),
|
||||
day_period: [Night, Morning, Noon, Evening],
|
||||
),
|
||||
],
|
||||
)
|
@ -0,0 +1,14 @@
|
||||
SpawnEntry (
|
||||
name: "April Fools Tundra Snow",
|
||||
note: "April Fools NPCs",
|
||||
rules: [
|
||||
Pack(
|
||||
groups: [
|
||||
(3, (3, 6, "common.entity.calendar.april_fools.aggressive.trickster")),
|
||||
],
|
||||
spawn_mode: Land,
|
||||
calendar_events: Some([AprilFools]),
|
||||
day_period: [Night, Morning, Noon, Evening],
|
||||
),
|
||||
],
|
||||
)
|
@ -8,6 +8,7 @@ use strum::EnumIter;
|
||||
pub enum CalendarEvent {
|
||||
Christmas = 0,
|
||||
Halloween = 1,
|
||||
AprilFools = 2,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Default, PartialEq, Eq, Serialize, Deserialize)]
|
||||
@ -43,6 +44,10 @@ impl Calendar {
|
||||
this.events.push(CalendarEvent::Halloween);
|
||||
}
|
||||
|
||||
if now.month() == 4 && now.day() == 1 {
|
||||
this.events.push(CalendarEvent::AprilFools);
|
||||
}
|
||||
|
||||
this
|
||||
}
|
||||
}
|
||||
|
@ -157,6 +157,7 @@ lazy_static! {
|
||||
BuffKind::Parried => "parried",
|
||||
BuffKind::PotionSickness => "potion_sickness",
|
||||
BuffKind::Reckless => "reckless",
|
||||
BuffKind::Polymorphed(_) => "polymorphed",
|
||||
};
|
||||
let mut buff_parser = HashMap::new();
|
||||
for kind in BuffKind::iter() {
|
||||
|
@ -31,7 +31,7 @@ use super::{BuffKind, Collider, Density, Mass, Scale};
|
||||
|
||||
make_case_elim!(
|
||||
body,
|
||||
#[derive(Copy, Clone, Debug, Display, PartialEq, Eq, Hash, Serialize, Deserialize)]
|
||||
#[derive(Copy, Clone, Debug, Display, PartialEq, PartialOrd, Ord, Eq, Hash, Serialize, Deserialize)]
|
||||
#[repr(u32)]
|
||||
pub enum Body {
|
||||
Humanoid(body: humanoid::Body) = 0,
|
||||
@ -54,6 +54,16 @@ make_case_elim!(
|
||||
}
|
||||
);
|
||||
|
||||
// Implemented for Buff, to be able to implement EnumIter.
|
||||
impl Default for Body {
|
||||
fn default() -> Self {
|
||||
Body::QuadrupedSmall(quadruped_small::Body {
|
||||
species: quadruped_small::Species::Frog,
|
||||
body_type: quadruped_small::BodyType::Female,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
/// Data representing data generic to the body together with per-species data.
|
||||
///
|
||||
/// NOTE: Deliberately don't (yet?) implement serialize.
|
||||
|
@ -1,7 +1,7 @@
|
||||
use rand::{seq::SliceRandom, thread_rng};
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
|
||||
pub struct Body {
|
||||
pub species: Species,
|
||||
pub body_type: BodyType,
|
||||
@ -25,7 +25,7 @@ impl From<Body> for super::Body {
|
||||
fn from(body: Body) -> Self { super::Body::Arthropod(body) }
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
|
||||
#[repr(u32)]
|
||||
pub enum Species {
|
||||
Tarantula = 0,
|
||||
@ -99,7 +99,7 @@ impl<'a, SpeciesMeta: 'a> IntoIterator for &'a AllSpecies<SpeciesMeta> {
|
||||
fn into_iter(self) -> Self::IntoIter { ALL_SPECIES.iter().copied() }
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
|
||||
#[repr(u32)]
|
||||
pub enum BodyType {
|
||||
Female = 0,
|
||||
|
@ -4,7 +4,7 @@ use serde::{Deserialize, Serialize};
|
||||
|
||||
make_proj_elim!(
|
||||
body,
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
|
||||
pub struct Body {
|
||||
pub species: Species,
|
||||
pub body_type: BodyType,
|
||||
@ -31,7 +31,7 @@ impl From<Body> for super::Body {
|
||||
|
||||
make_case_elim!(
|
||||
species,
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
|
||||
#[repr(u32)]
|
||||
pub enum Species {
|
||||
Ogre = 0,
|
||||
@ -158,7 +158,7 @@ impl<'a, SpeciesMeta: 'a> IntoIterator for &'a AllSpecies<SpeciesMeta> {
|
||||
|
||||
make_case_elim!(
|
||||
body_type,
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
|
||||
#[repr(u32)]
|
||||
pub enum BodyType {
|
||||
Female = 0,
|
||||
|
@ -4,7 +4,7 @@ use serde::{Deserialize, Serialize};
|
||||
|
||||
make_proj_elim!(
|
||||
body,
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
|
||||
pub struct Body {
|
||||
pub species: Species,
|
||||
pub body_type: BodyType,
|
||||
@ -31,7 +31,7 @@ impl From<Body> for super::Body {
|
||||
|
||||
make_case_elim!(
|
||||
species,
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
|
||||
#[repr(u32)]
|
||||
pub enum Species {
|
||||
Gnome = 0,
|
||||
@ -114,7 +114,7 @@ impl<'a, SpeciesMeta: 'a> IntoIterator for &'a AllSpecies<SpeciesMeta> {
|
||||
|
||||
make_case_elim!(
|
||||
body_type,
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
|
||||
#[repr(u32)]
|
||||
pub enum BodyType {
|
||||
Female = 0,
|
||||
|
@ -4,7 +4,7 @@ use serde::{Deserialize, Serialize};
|
||||
|
||||
make_proj_elim!(
|
||||
body,
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
|
||||
pub struct Body {
|
||||
pub species: Species,
|
||||
pub body_type: BodyType,
|
||||
@ -31,7 +31,7 @@ impl From<Body> for super::Body {
|
||||
|
||||
make_case_elim!(
|
||||
species,
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
|
||||
#[repr(u32)]
|
||||
pub enum Species {
|
||||
Phoenix = 0,
|
||||
@ -98,7 +98,7 @@ impl<'a, SpeciesMeta: 'a> IntoIterator for &'a AllSpecies<SpeciesMeta> {
|
||||
|
||||
make_case_elim!(
|
||||
body_type,
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
|
||||
#[repr(u32)]
|
||||
pub enum BodyType {
|
||||
Female = 0,
|
||||
|
@ -5,7 +5,7 @@ use strum::{Display, EnumString};
|
||||
|
||||
make_proj_elim!(
|
||||
body,
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
|
||||
pub struct Body {
|
||||
pub species: Species,
|
||||
pub body_type: BodyType,
|
||||
@ -33,7 +33,18 @@ impl From<Body> for super::Body {
|
||||
make_case_elim!(
|
||||
species,
|
||||
#[derive(
|
||||
Copy, Clone, Debug, Display, EnumString, PartialEq, Eq, Hash, Serialize, Deserialize,
|
||||
Copy,
|
||||
Clone,
|
||||
Debug,
|
||||
Display,
|
||||
EnumString,
|
||||
PartialEq,
|
||||
Eq,
|
||||
PartialOrd,
|
||||
Ord,
|
||||
Hash,
|
||||
Serialize,
|
||||
Deserialize,
|
||||
)]
|
||||
#[repr(u32)]
|
||||
pub enum Species {
|
||||
@ -134,7 +145,18 @@ impl<'a, SpeciesMeta: 'a> IntoIterator for &'a AllSpecies<SpeciesMeta> {
|
||||
make_case_elim!(
|
||||
body_type,
|
||||
#[derive(
|
||||
Copy, Clone, Debug, Display, EnumString, PartialEq, Eq, Hash, Serialize, Deserialize,
|
||||
Copy,
|
||||
Clone,
|
||||
Debug,
|
||||
Display,
|
||||
EnumString,
|
||||
PartialEq,
|
||||
Eq,
|
||||
PartialOrd,
|
||||
Ord,
|
||||
Hash,
|
||||
Serialize,
|
||||
Deserialize,
|
||||
)]
|
||||
#[repr(u32)]
|
||||
pub enum BodyType {
|
||||
|
@ -4,7 +4,7 @@ use serde::{Deserialize, Serialize};
|
||||
|
||||
make_proj_elim!(
|
||||
body,
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
|
||||
pub struct Body {
|
||||
pub species: Species,
|
||||
pub body_type: BodyType,
|
||||
@ -31,7 +31,7 @@ impl From<Body> for super::Body {
|
||||
|
||||
make_case_elim!(
|
||||
species,
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
|
||||
#[repr(u32)]
|
||||
pub enum Species {
|
||||
Reddragon = 0,
|
||||
@ -68,7 +68,7 @@ impl<'a, SpeciesMeta: 'a> IntoIterator for &'a AllSpecies<SpeciesMeta> {
|
||||
|
||||
make_case_elim!(
|
||||
body_type,
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
|
||||
#[repr(u32)]
|
||||
pub enum BodyType {
|
||||
Female = 0,
|
||||
|
@ -4,7 +4,7 @@ use serde::{Deserialize, Serialize};
|
||||
|
||||
make_proj_elim!(
|
||||
body,
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
|
||||
pub struct Body {
|
||||
pub species: Species,
|
||||
pub body_type: BodyType,
|
||||
@ -31,7 +31,7 @@ impl From<Body> for super::Body {
|
||||
|
||||
make_case_elim!(
|
||||
species,
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
|
||||
#[repr(u32)]
|
||||
pub enum Species {
|
||||
Marlin = 0,
|
||||
@ -71,7 +71,7 @@ impl<'a, SpeciesMeta: 'a> IntoIterator for &'a AllSpecies<SpeciesMeta> {
|
||||
|
||||
make_case_elim!(
|
||||
body_type,
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
|
||||
#[repr(u32)]
|
||||
pub enum BodyType {
|
||||
Female = 0,
|
||||
|
@ -4,7 +4,7 @@ use serde::{Deserialize, Serialize};
|
||||
|
||||
make_proj_elim!(
|
||||
body,
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
|
||||
pub struct Body {
|
||||
pub species: Species,
|
||||
pub body_type: BodyType,
|
||||
@ -31,7 +31,7 @@ impl From<Body> for super::Body {
|
||||
|
||||
make_case_elim!(
|
||||
species,
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
|
||||
#[repr(u32)]
|
||||
pub enum Species {
|
||||
Clownfish = 0,
|
||||
@ -71,7 +71,7 @@ impl<'a, SpeciesMeta: 'a> IntoIterator for &'a AllSpecies<SpeciesMeta> {
|
||||
|
||||
make_case_elim!(
|
||||
body_type,
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
|
||||
#[repr(u32)]
|
||||
pub enum BodyType {
|
||||
Female = 0,
|
||||
|
@ -4,7 +4,7 @@ use serde::{Deserialize, Serialize};
|
||||
|
||||
make_proj_elim!(
|
||||
body,
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
|
||||
pub struct Body {
|
||||
pub species: Species,
|
||||
pub body_type: BodyType,
|
||||
@ -31,7 +31,7 @@ impl From<Body> for super::Body {
|
||||
|
||||
make_case_elim!(
|
||||
species,
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
|
||||
#[repr(u32)]
|
||||
pub enum Species {
|
||||
StoneGolem = 0,
|
||||
@ -82,7 +82,7 @@ impl<'a, SpeciesMeta: 'a> IntoIterator for &'a AllSpecies<SpeciesMeta> {
|
||||
|
||||
make_case_elim!(
|
||||
body_type,
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
|
||||
#[repr(u32)]
|
||||
pub enum BodyType {
|
||||
Female = 0,
|
||||
|
@ -5,7 +5,7 @@ use serde_repr::{Deserialize_repr, Serialize_repr};
|
||||
|
||||
make_proj_elim!(
|
||||
body,
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
|
||||
pub struct Body {
|
||||
pub species: Species,
|
||||
pub body_type: BodyType,
|
||||
@ -90,7 +90,7 @@ impl From<Body> for super::Body {
|
||||
|
||||
make_case_elim!(
|
||||
species,
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
|
||||
#[repr(u32)]
|
||||
pub enum Species {
|
||||
Danari = 0,
|
||||
@ -413,7 +413,7 @@ impl Species {
|
||||
|
||||
make_case_elim!(
|
||||
body_type,
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
|
||||
#[repr(u32)]
|
||||
pub enum BodyType {
|
||||
Female = 0,
|
||||
|
@ -18,7 +18,7 @@ use vek::Vec3;
|
||||
|
||||
make_case_elim!(
|
||||
armor,
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
|
||||
#[repr(u32)]
|
||||
pub enum ItemDropArmorKind {
|
||||
Shoulder = 0,
|
||||
@ -38,7 +38,7 @@ make_case_elim!(
|
||||
|
||||
make_case_elim!(
|
||||
body,
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
|
||||
#[repr(u32)]
|
||||
pub enum Body {
|
||||
Tool(tool: ToolKind) = 0,
|
||||
|
@ -9,7 +9,7 @@ use vek::Vec3;
|
||||
|
||||
make_case_elim!(
|
||||
body,
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
|
||||
#[repr(u32)]
|
||||
pub enum Body {
|
||||
Arrow = 0,
|
||||
|
@ -5,7 +5,7 @@ use strum::{Display, EnumString};
|
||||
|
||||
make_proj_elim!(
|
||||
body,
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
|
||||
pub struct Body {
|
||||
pub species: Species,
|
||||
pub body_type: BodyType,
|
||||
@ -35,7 +35,18 @@ impl From<Body> for super::Body {
|
||||
make_case_elim!(
|
||||
species,
|
||||
#[derive(
|
||||
Copy, Clone, Debug, Display, EnumString, PartialEq, Eq, Hash, Serialize, Deserialize,
|
||||
Copy,
|
||||
Clone,
|
||||
Debug,
|
||||
Display,
|
||||
EnumString,
|
||||
PartialEq,
|
||||
Eq,
|
||||
PartialOrd,
|
||||
Ord,
|
||||
Hash,
|
||||
Serialize,
|
||||
Deserialize,
|
||||
)]
|
||||
#[repr(u32)]
|
||||
pub enum Species {
|
||||
@ -158,7 +169,18 @@ impl<'a, SpeciesMeta: 'a> IntoIterator for &'a AllSpecies<SpeciesMeta> {
|
||||
make_case_elim!(
|
||||
body_type,
|
||||
#[derive(
|
||||
Copy, Clone, Debug, Display, EnumString, PartialEq, Eq, Hash, Serialize, Deserialize,
|
||||
Copy,
|
||||
Clone,
|
||||
Debug,
|
||||
Display,
|
||||
EnumString,
|
||||
PartialEq,
|
||||
Eq,
|
||||
PartialOrd,
|
||||
Ord,
|
||||
Hash,
|
||||
Serialize,
|
||||
Deserialize,
|
||||
)]
|
||||
#[repr(u32)]
|
||||
pub enum BodyType {
|
||||
|
@ -5,7 +5,7 @@ use strum::{Display, EnumString};
|
||||
|
||||
make_proj_elim!(
|
||||
body,
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
|
||||
pub struct Body {
|
||||
pub species: Species,
|
||||
pub body_type: BodyType,
|
||||
@ -32,7 +32,20 @@ impl From<Body> for super::Body {
|
||||
|
||||
// Renaming any enum entries here (re-ordering is fine) will require a
|
||||
// database migration to ensure pets correctly de-serialize on player login.
|
||||
#[derive(Copy, Clone, Debug, Display, EnumString, PartialEq, Eq, Hash, Serialize, Deserialize)]
|
||||
#[derive(
|
||||
Copy,
|
||||
Clone,
|
||||
Debug,
|
||||
Display,
|
||||
EnumString,
|
||||
PartialEq,
|
||||
Eq,
|
||||
PartialOrd,
|
||||
Ord,
|
||||
Hash,
|
||||
Serialize,
|
||||
Deserialize,
|
||||
)]
|
||||
#[repr(u32)]
|
||||
pub enum Species {
|
||||
Grolgar = 0,
|
||||
@ -213,7 +226,18 @@ impl<'a, SpeciesMeta: 'a> IntoIterator for &'a AllSpecies<SpeciesMeta> {
|
||||
make_case_elim!(
|
||||
body_type,
|
||||
#[derive(
|
||||
Copy, Clone, Debug, Display, EnumString, PartialEq, Eq, Hash, Serialize, Deserialize,
|
||||
Copy,
|
||||
Clone,
|
||||
Debug,
|
||||
Display,
|
||||
EnumString,
|
||||
PartialEq,
|
||||
Eq,
|
||||
PartialOrd,
|
||||
Ord,
|
||||
Hash,
|
||||
Serialize,
|
||||
Deserialize,
|
||||
)]
|
||||
#[repr(u32)]
|
||||
pub enum BodyType {
|
||||
|
@ -5,7 +5,7 @@ use strum::{Display, EnumString};
|
||||
|
||||
make_proj_elim!(
|
||||
body,
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
|
||||
pub struct Body {
|
||||
pub species: Species,
|
||||
pub body_type: BodyType,
|
||||
@ -32,7 +32,20 @@ impl From<Body> for super::Body {
|
||||
|
||||
// Renaming any enum entries here (re-ordering is fine) will require a
|
||||
// database migration to ensure pets correctly de-serialize on player login.
|
||||
#[derive(Copy, Clone, Debug, Display, EnumString, PartialEq, Eq, Hash, Serialize, Deserialize)]
|
||||
#[derive(
|
||||
Copy,
|
||||
Clone,
|
||||
Debug,
|
||||
Display,
|
||||
EnumString,
|
||||
PartialEq,
|
||||
Eq,
|
||||
PartialOrd,
|
||||
Ord,
|
||||
Hash,
|
||||
Serialize,
|
||||
Deserialize,
|
||||
)]
|
||||
#[repr(u32)]
|
||||
pub enum Species {
|
||||
Pig = 0,
|
||||
@ -177,7 +190,18 @@ impl<'a, SpeciesMeta: 'a> IntoIterator for &'a AllSpecies<SpeciesMeta> {
|
||||
make_case_elim!(
|
||||
body_type,
|
||||
#[derive(
|
||||
Copy, Clone, Debug, Display, EnumString, PartialEq, Eq, Hash, Serialize, Deserialize,
|
||||
Copy,
|
||||
Clone,
|
||||
Debug,
|
||||
Display,
|
||||
EnumString,
|
||||
PartialEq,
|
||||
Eq,
|
||||
PartialOrd,
|
||||
Ord,
|
||||
Hash,
|
||||
Serialize,
|
||||
Deserialize,
|
||||
)]
|
||||
#[repr(u32)]
|
||||
pub enum BodyType {
|
||||
|
@ -21,7 +21,7 @@ pub const ALL_SHIPS: [Body; 2] = [Body::SailBoat, Body::Galleon];
|
||||
|
||||
make_case_elim!(
|
||||
body,
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
|
||||
#[repr(u32)]
|
||||
pub enum Body {
|
||||
DefaultAirship = 0,
|
||||
|
@ -1,7 +1,7 @@
|
||||
use rand::{seq::SliceRandom, thread_rng};
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
|
||||
pub struct Body {
|
||||
pub species: Species,
|
||||
pub body_type: BodyType,
|
||||
@ -25,7 +25,7 @@ impl From<Body> for super::Body {
|
||||
fn from(body: Body) -> Self { super::Body::Theropod(body) }
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
|
||||
#[repr(u32)]
|
||||
pub enum Species {
|
||||
Archaeos = 0,
|
||||
@ -95,7 +95,7 @@ impl<'a, SpeciesMeta: 'a> IntoIterator for &'a AllSpecies<SpeciesMeta> {
|
||||
fn into_iter(self) -> Self::IntoIter { ALL_SPECIES.iter().copied() }
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
|
||||
#[repr(u32)]
|
||||
pub enum BodyType {
|
||||
Female = 0,
|
||||
|
@ -13,6 +13,8 @@ use serde::{Deserialize, Serialize};
|
||||
use specs::{Component, DerefFlaggedStorage, VecStorage};
|
||||
use strum::EnumIter;
|
||||
|
||||
use super::Body;
|
||||
|
||||
/// De/buff Kind.
|
||||
/// This is used to determine what effects a buff will have
|
||||
#[derive(
|
||||
@ -107,6 +109,8 @@ pub enum BuffKind {
|
||||
/// Results from drinking a potion.
|
||||
/// Decreases the health gained from subsequent potions.
|
||||
PotionSickness,
|
||||
// Changed into another body.
|
||||
Polymorphed(Body),
|
||||
}
|
||||
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
@ -136,7 +140,8 @@ impl BuffKind {
|
||||
| BuffKind::Ensnared
|
||||
| BuffKind::Poisoned
|
||||
| BuffKind::Parried
|
||||
| BuffKind::PotionSickness => false,
|
||||
| BuffKind::PotionSickness
|
||||
| BuffKind::Polymorphed(_) => false,
|
||||
}
|
||||
}
|
||||
|
||||
@ -150,149 +155,17 @@ impl BuffKind {
|
||||
/// Checks if multiple instances of the buff should be processed, instead of
|
||||
/// only the strongest.
|
||||
pub fn stacks(self) -> bool { matches!(self, BuffKind::PotionSickness) }
|
||||
}
|
||||
|
||||
// Struct used to store data relevant to a buff
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Serialize, Deserialize)]
|
||||
pub struct BuffData {
|
||||
pub strength: f32,
|
||||
pub duration: Option<Secs>,
|
||||
pub delay: Option<Secs>,
|
||||
}
|
||||
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
impl BuffData {
|
||||
pub fn new(strength: f32, duration: Option<Secs>, delay: Option<Secs>) -> Self {
|
||||
Self {
|
||||
strength,
|
||||
duration,
|
||||
delay,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// De/buff category ID.
|
||||
/// Similar to `BuffKind`, but to mark a category (for more generic usage, like
|
||||
/// positive/negative buffs).
|
||||
#[derive(Clone, Copy, Eq, PartialEq, Debug, Serialize, Deserialize)]
|
||||
pub enum BuffCategory {
|
||||
Natural,
|
||||
Physical,
|
||||
Magical,
|
||||
Divine,
|
||||
PersistOnDeath,
|
||||
FromActiveAura(Uid, AuraKey),
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||
pub enum ModifierKind {
|
||||
Additive,
|
||||
Fractional,
|
||||
}
|
||||
|
||||
/// Data indicating and configuring behaviour of a de/buff.
|
||||
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||
pub enum BuffEffect {
|
||||
/// Periodically damages or heals entity
|
||||
HealthChangeOverTime {
|
||||
rate: f32,
|
||||
kind: ModifierKind,
|
||||
instance: u64,
|
||||
},
|
||||
/// Periodically consume entity energy
|
||||
EnergyChangeOverTime { rate: f32, kind: ModifierKind },
|
||||
/// Changes maximum health by a certain amount
|
||||
MaxHealthModifier { value: f32, kind: ModifierKind },
|
||||
/// Changes maximum energy by a certain amount
|
||||
MaxEnergyModifier { value: f32, kind: ModifierKind },
|
||||
/// Reduces damage after armor is accounted for by this fraction
|
||||
DamageReduction(f32),
|
||||
/// Gradually changes an entities max health over time
|
||||
MaxHealthChangeOverTime {
|
||||
rate: f32,
|
||||
kind: ModifierKind,
|
||||
target_fraction: f32,
|
||||
},
|
||||
/// Modifies move speed of target
|
||||
MovementSpeed(f32),
|
||||
/// Modifies attack speed of target
|
||||
AttackSpeed(f32),
|
||||
/// Modifies ground friction of target
|
||||
GroundFriction(f32),
|
||||
/// Reduces poise damage taken after armor is accounted for by this fraction
|
||||
PoiseReduction(f32),
|
||||
/// Reduces amount healed by consumables
|
||||
HealReduction(f32),
|
||||
/// Increases poise damage dealt when health is lost
|
||||
PoiseDamageFromLostHealth { initial_health: f32, strength: f32 },
|
||||
/// Modifier to the amount of damage dealt with attacks
|
||||
AttackDamage(f32),
|
||||
/// Multiplies crit chance of attacks
|
||||
CriticalChance(f32),
|
||||
}
|
||||
|
||||
/// Actual de/buff.
|
||||
/// Buff can timeout after some time if `time` is Some. If `time` is None,
|
||||
/// Buff will last indefinitely, until removed manually (by some action, like
|
||||
/// uncursing).
|
||||
///
|
||||
/// Buff has a kind, which is used to determine the effects in a builder
|
||||
/// function.
|
||||
///
|
||||
/// To provide more classification info when needed,
|
||||
/// buff can be in one or more buff category.
|
||||
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||
pub struct Buff {
|
||||
pub kind: BuffKind,
|
||||
pub data: BuffData,
|
||||
pub cat_ids: Vec<BuffCategory>,
|
||||
pub end_time: Option<Time>,
|
||||
pub start_time: Time,
|
||||
pub effects: Vec<BuffEffect>,
|
||||
pub source: BuffSource,
|
||||
}
|
||||
|
||||
/// Information about whether buff addition or removal was requested.
|
||||
/// This to implement "on_add" and "on_remove" hooks for constant buffs.
|
||||
#[derive(Clone, Debug)]
|
||||
pub enum BuffChange {
|
||||
/// Adds this buff.
|
||||
Add(Buff),
|
||||
/// Removes all buffs with this ID.
|
||||
RemoveByKind(BuffKind),
|
||||
/// Removes all buffs with this ID, but not debuffs.
|
||||
RemoveFromController(BuffKind),
|
||||
/// Removes buffs of these indices (first vec is for active buffs, second is
|
||||
/// for inactive buffs), should only be called when buffs expire
|
||||
RemoveById(Vec<BuffId>),
|
||||
/// Removes buffs of these categories (first vec is of categories of which
|
||||
/// all are required, second vec is of categories of which at least one is
|
||||
/// required, third vec is of categories that will not be removed)
|
||||
RemoveByCategory {
|
||||
all_required: Vec<BuffCategory>,
|
||||
any_required: Vec<BuffCategory>,
|
||||
none_required: Vec<BuffCategory>,
|
||||
},
|
||||
// Refreshes durations of all buffs with this kind
|
||||
Refresh(BuffKind),
|
||||
}
|
||||
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
impl Buff {
|
||||
/// Builder function for buffs
|
||||
pub fn new(
|
||||
kind: BuffKind,
|
||||
data: BuffData,
|
||||
cat_ids: Vec<BuffCategory>,
|
||||
source: BuffSource,
|
||||
time: Time,
|
||||
pub fn effects(
|
||||
&self,
|
||||
data: &BuffData,
|
||||
stats: Option<&Stats>,
|
||||
health: Option<&Health>,
|
||||
) -> Self {
|
||||
) -> Vec<BuffEffect> {
|
||||
// Normalized nonlinear scaling
|
||||
let nn_scaling = |a| a / (a + 0.5);
|
||||
let instance = rand::random();
|
||||
let effects = match kind {
|
||||
match self {
|
||||
BuffKind::Bleeding => vec![BuffEffect::HealthChangeOverTime {
|
||||
rate: -data.strength,
|
||||
kind: ModifierKind::Additive,
|
||||
@ -397,7 +270,151 @@ impl Buff {
|
||||
BuffEffect::DamageReduction(-data.strength),
|
||||
BuffEffect::AttackDamage(1.0 + data.strength),
|
||||
],
|
||||
};
|
||||
BuffKind::Polymorphed(body) => vec![BuffEffect::BodyChange(*body)],
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Struct used to store data relevant to a buff
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Serialize, Deserialize)]
|
||||
pub struct BuffData {
|
||||
pub strength: f32,
|
||||
pub duration: Option<Secs>,
|
||||
pub delay: Option<Secs>,
|
||||
}
|
||||
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
impl BuffData {
|
||||
pub fn new(strength: f32, duration: Option<Secs>, delay: Option<Secs>) -> Self {
|
||||
Self {
|
||||
strength,
|
||||
duration,
|
||||
delay,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// De/buff category ID.
|
||||
/// Similar to `BuffKind`, but to mark a category (for more generic usage, like
|
||||
/// positive/negative buffs).
|
||||
#[derive(Clone, Copy, Eq, PartialEq, Debug, Serialize, Deserialize)]
|
||||
pub enum BuffCategory {
|
||||
Natural,
|
||||
Physical,
|
||||
Magical,
|
||||
Divine,
|
||||
PersistOnDeath,
|
||||
FromActiveAura(Uid, AuraKey),
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||
pub enum ModifierKind {
|
||||
Additive,
|
||||
Fractional,
|
||||
}
|
||||
|
||||
/// Data indicating and configuring behaviour of a de/buff.
|
||||
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||
pub enum BuffEffect {
|
||||
/// Periodically damages or heals entity
|
||||
HealthChangeOverTime {
|
||||
rate: f32,
|
||||
kind: ModifierKind,
|
||||
instance: u64,
|
||||
},
|
||||
/// Periodically consume entity energy
|
||||
EnergyChangeOverTime { rate: f32, kind: ModifierKind },
|
||||
/// Changes maximum health by a certain amount
|
||||
MaxHealthModifier { value: f32, kind: ModifierKind },
|
||||
/// Changes maximum energy by a certain amount
|
||||
MaxEnergyModifier { value: f32, kind: ModifierKind },
|
||||
/// Reduces damage after armor is accounted for by this fraction
|
||||
DamageReduction(f32),
|
||||
/// Gradually changes an entities max health over time
|
||||
MaxHealthChangeOverTime {
|
||||
rate: f32,
|
||||
kind: ModifierKind,
|
||||
target_fraction: f32,
|
||||
},
|
||||
/// Modifies move speed of target
|
||||
MovementSpeed(f32),
|
||||
/// Modifies attack speed of target
|
||||
AttackSpeed(f32),
|
||||
/// Modifies ground friction of target
|
||||
GroundFriction(f32),
|
||||
/// Reduces poise damage taken after armor is accounted for by this fraction
|
||||
PoiseReduction(f32),
|
||||
/// Reduces amount healed by consumables
|
||||
HealReduction(f32),
|
||||
/// Increases poise damage dealt when health is lost
|
||||
PoiseDamageFromLostHealth { initial_health: f32, strength: f32 },
|
||||
/// Modifier to the amount of damage dealt with attacks
|
||||
AttackDamage(f32),
|
||||
/// Multiplies crit chance of attacks
|
||||
CriticalChance(f32),
|
||||
/// Changes body.
|
||||
BodyChange(Body),
|
||||
}
|
||||
|
||||
/// Actual de/buff.
|
||||
/// Buff can timeout after some time if `time` is Some. If `time` is None,
|
||||
/// Buff will last indefinitely, until removed manually (by some action, like
|
||||
/// uncursing).
|
||||
///
|
||||
/// Buff has a kind, which is used to determine the effects in a builder
|
||||
/// function.
|
||||
///
|
||||
/// To provide more classification info when needed,
|
||||
/// buff can be in one or more buff category.
|
||||
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||
pub struct Buff {
|
||||
pub kind: BuffKind,
|
||||
pub data: BuffData,
|
||||
pub cat_ids: Vec<BuffCategory>,
|
||||
pub end_time: Option<Time>,
|
||||
pub start_time: Time,
|
||||
pub effects: Vec<BuffEffect>,
|
||||
pub source: BuffSource,
|
||||
}
|
||||
|
||||
/// Information about whether buff addition or removal was requested.
|
||||
/// This to implement "on_add" and "on_remove" hooks for constant buffs.
|
||||
#[derive(Clone, Debug)]
|
||||
pub enum BuffChange {
|
||||
/// Adds this buff.
|
||||
Add(Buff),
|
||||
/// Removes all buffs with this ID.
|
||||
RemoveByKind(BuffKind),
|
||||
/// Removes all buffs with this ID, but not debuffs.
|
||||
RemoveFromController(BuffKind),
|
||||
/// Removes buffs of these indices (first vec is for active buffs, second is
|
||||
/// for inactive buffs), should only be called when buffs expire
|
||||
RemoveById(Vec<BuffId>),
|
||||
/// Removes buffs of these categories (first vec is of categories of which
|
||||
/// all are required, second vec is of categories of which at least one is
|
||||
/// required, third vec is of categories that will not be removed)
|
||||
RemoveByCategory {
|
||||
all_required: Vec<BuffCategory>,
|
||||
any_required: Vec<BuffCategory>,
|
||||
none_required: Vec<BuffCategory>,
|
||||
},
|
||||
// Refreshes durations of all buffs with this kind
|
||||
Refresh(BuffKind),
|
||||
}
|
||||
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
impl Buff {
|
||||
/// Builder function for buffs
|
||||
pub fn new(
|
||||
kind: BuffKind,
|
||||
data: BuffData,
|
||||
cat_ids: Vec<BuffCategory>,
|
||||
source: BuffSource,
|
||||
time: Time,
|
||||
stats: Option<&Stats>,
|
||||
health: Option<&Health>,
|
||||
) -> Self {
|
||||
let effects = kind.effects(&data, stats, health);
|
||||
let start_time = Time(time.0 + data.delay.map_or(0.0, |delay| delay.0));
|
||||
let end_time = if cat_ids
|
||||
.iter()
|
||||
|
@ -265,6 +265,23 @@ impl TagExampleInfo for ItemTag {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||
pub enum Effects {
|
||||
Any(Vec<Effect>),
|
||||
All(Vec<Effect>),
|
||||
One(Effect),
|
||||
}
|
||||
|
||||
impl Effects {
|
||||
pub fn effects(&self) -> &[Effect] {
|
||||
match self {
|
||||
Effects::Any(effects) => effects,
|
||||
Effects::All(effects) => effects,
|
||||
Effects::One(effect) => std::slice::from_ref(effect),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||
pub enum ItemKind {
|
||||
/// Something wieldable
|
||||
@ -275,7 +292,7 @@ pub enum ItemKind {
|
||||
Glider,
|
||||
Consumable {
|
||||
kind: ConsumableKind,
|
||||
effects: Vec<Effect>,
|
||||
effects: Effects,
|
||||
},
|
||||
Throwable {
|
||||
kind: Throwable,
|
||||
|
@ -1046,6 +1046,7 @@ impl TradePricing {
|
||||
} else if let ItemKind::Consumable { kind: _, effects } = &*i.kind() {
|
||||
(
|
||||
effects
|
||||
.effects()
|
||||
.iter()
|
||||
.map(|e| {
|
||||
if let crate::effect::Effect::Buff(b) = e {
|
||||
|
@ -2,6 +2,8 @@ use serde::{Deserialize, Serialize};
|
||||
use specs::{Component, DerefFlaggedStorage};
|
||||
use std::{error::Error, fmt};
|
||||
|
||||
use super::Body;
|
||||
|
||||
#[derive(Debug)]
|
||||
#[allow(dead_code)] // TODO: remove once trade sim hits master
|
||||
pub enum StatChangeError {
|
||||
@ -48,6 +50,7 @@ impl Error for StatChangeError {}
|
||||
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||
pub struct Stats {
|
||||
pub name: String,
|
||||
pub original_body: Body,
|
||||
pub damage_reduction: f32,
|
||||
pub poise_reduction: f32,
|
||||
pub heal_multiplier: f32,
|
||||
@ -62,9 +65,10 @@ pub struct Stats {
|
||||
}
|
||||
|
||||
impl Stats {
|
||||
pub fn new(name: String) -> Self {
|
||||
pub fn new(name: String, body: Body) -> Self {
|
||||
Self {
|
||||
name,
|
||||
original_body: body,
|
||||
damage_reduction: 0.0,
|
||||
poise_reduction: 0.0,
|
||||
heal_multiplier: 1.0,
|
||||
@ -81,12 +85,14 @@ impl Stats {
|
||||
|
||||
/// Creates an empty `Stats` instance - used during character loading from
|
||||
/// the database
|
||||
pub fn empty() -> Self { Self::new("".to_string()) }
|
||||
pub fn empty(body: Body) -> Self { Self::new("".to_string(), body) }
|
||||
|
||||
/// Resets temporary modifiers to default values
|
||||
pub fn reset_temp_modifiers(&mut self) {
|
||||
// TODO: Figure out how to avoid clone
|
||||
*self = Self::new(self.name.clone());
|
||||
let name = std::mem::take(&mut self.name);
|
||||
let body = self.original_body;
|
||||
|
||||
*self = Self::new(name, body);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -111,7 +111,7 @@ impl CharacterBehavior for Data {
|
||||
}
|
||||
};
|
||||
|
||||
let stats = comp::Stats::new("Summon".to_string());
|
||||
let stats = comp::Stats::new("Summon".to_string(), body);
|
||||
|
||||
let health = self.static_data.summon_info.has_health.then(|| {
|
||||
let health_level = skill_set
|
||||
|
@ -125,10 +125,11 @@ impl<'a> System<'a> for Sys {
|
||||
}
|
||||
}
|
||||
|
||||
for (entity, buff_comp, mut stat, health, energy, physics_state) in (
|
||||
for (entity, buff_comp, mut stat, mut body, health, energy, physics_state) in (
|
||||
&read_data.entities,
|
||||
&read_data.buffs,
|
||||
&mut stats,
|
||||
&mut bodies,
|
||||
&read_data.healths,
|
||||
&read_data.energies,
|
||||
read_data.physics_states.maybe(),
|
||||
@ -330,6 +331,8 @@ impl<'a> System<'a> for Sys {
|
||||
// Call to reset stats to base values
|
||||
stat.reset_temp_modifiers();
|
||||
|
||||
let mut body_override = stat.original_body;
|
||||
|
||||
// Iterator over the lists of buffs by kind
|
||||
let mut buff_kinds = buff_comp
|
||||
.kinds
|
||||
@ -368,6 +371,7 @@ impl<'a> System<'a> for Sys {
|
||||
kind_start_time,
|
||||
&read_data,
|
||||
&mut stat,
|
||||
&mut body_override,
|
||||
health,
|
||||
energy,
|
||||
entity,
|
||||
@ -382,6 +386,11 @@ impl<'a> System<'a> for Sys {
|
||||
}
|
||||
}
|
||||
|
||||
// Update body if needed.
|
||||
if body_override != *body {
|
||||
*body = body_override;
|
||||
}
|
||||
|
||||
// Remove buffs that expire
|
||||
if !expired_buffs.is_empty() {
|
||||
server_emitter.emit(ServerEvent::Buff {
|
||||
@ -414,6 +423,7 @@ fn execute_effect(
|
||||
buff_kind_start_time: Time,
|
||||
read_data: &ReadData,
|
||||
stat: &mut Stats,
|
||||
body_override: &mut Body,
|
||||
health: &Health,
|
||||
energy: &Energy,
|
||||
entity: Entity,
|
||||
@ -592,5 +602,6 @@ fn execute_effect(
|
||||
BuffEffect::CriticalChance(cc) => {
|
||||
stat.crit_chance_modifier *= *cc;
|
||||
},
|
||||
BuffEffect::BodyChange(b) => *body_override = *b,
|
||||
};
|
||||
}
|
||||
|
@ -69,7 +69,7 @@ mod tests {
|
||||
.with(Poise::new(body))
|
||||
.with(skill_set)
|
||||
.with(PhysicsState::default())
|
||||
.with(Stats::empty())
|
||||
.with(Stats::empty(body))
|
||||
.with(Uid(1))
|
||||
.build()
|
||||
}
|
||||
|
@ -133,7 +133,7 @@ pub fn create_player(state: &mut State) -> Entity {
|
||||
))
|
||||
.with(Health::new(body, body.base_health()))
|
||||
.with(skill_set)
|
||||
.with(Stats::empty())
|
||||
.with(Stats::empty(body))
|
||||
.build()
|
||||
}
|
||||
|
||||
|
@ -15,11 +15,10 @@ use common::{
|
||||
comp::{
|
||||
self,
|
||||
agent::{Sound, SoundKind, Target},
|
||||
buff::BuffKind,
|
||||
inventory::slot::EquipSlot,
|
||||
item::{
|
||||
tool::{AbilitySpec, ToolKind},
|
||||
ConsumableKind, Item, ItemDesc, ItemKind,
|
||||
ConsumableKind, Effects, Item, ItemDesc, ItemKind,
|
||||
},
|
||||
item_drop,
|
||||
projectile::ProjectileConstructor,
|
||||
@ -541,39 +540,74 @@ impl<'a> AgentData<'a> {
|
||||
if heal_multiplier < 0.5 {
|
||||
return false;
|
||||
}
|
||||
// (healing_value, heal_reduction)
|
||||
let effect_healing_value = |effect: &Effect| -> (f32, f32) {
|
||||
let mut value = 0.0;
|
||||
let mut heal_reduction = 0.0;
|
||||
match effect {
|
||||
Effect::Health(HealthChange { amount, .. }) => {
|
||||
value += *amount;
|
||||
},
|
||||
Effect::Buff(BuffEffect { kind, data, .. }) => {
|
||||
if let Some(duration) = data.duration {
|
||||
for effect in kind.effects(data, self.stats, self.health) {
|
||||
match effect {
|
||||
comp::BuffEffect::HealthChangeOverTime { rate, kind, .. } => {
|
||||
let amount = match kind {
|
||||
comp::ModifierKind::Additive => rate * duration.0 as f32,
|
||||
comp::ModifierKind::Fractional => {
|
||||
(1.0 + rate).powf(duration.0 as f32)
|
||||
},
|
||||
};
|
||||
|
||||
value += amount;
|
||||
},
|
||||
comp::BuffEffect::HealReduction(amount) => {
|
||||
heal_reduction =
|
||||
heal_reduction + amount - heal_reduction * amount;
|
||||
},
|
||||
_ => {},
|
||||
}
|
||||
}
|
||||
value += data.strength * data.duration.map_or(0.0, |d| d.0 as f32);
|
||||
}
|
||||
},
|
||||
|
||||
_ => {},
|
||||
}
|
||||
|
||||
(value, heal_reduction)
|
||||
};
|
||||
let healing_value = |item: &Item| {
|
||||
let mut value = 0.0;
|
||||
let mut causes_potion_sickness = false;
|
||||
let mut heal_multiplier_value = 1.0;
|
||||
|
||||
if let ItemKind::Consumable { kind, effects, .. } = &*item.kind() {
|
||||
if matches!(kind, ConsumableKind::Drink)
|
||||
|| (relaxed && matches!(kind, ConsumableKind::Food))
|
||||
{
|
||||
for effect in effects.iter() {
|
||||
use BuffKind::*;
|
||||
match effect {
|
||||
Effect::Health(HealthChange { amount, .. }) => {
|
||||
value += *amount;
|
||||
},
|
||||
Effect::Buff(BuffEffect { kind, data, .. })
|
||||
if matches!(kind, Regeneration | Saturation | Potion) =>
|
||||
{
|
||||
value += data.strength * data.duration.map_or(0.0, |d| d.0 as f32);
|
||||
},
|
||||
Effect::Buff(BuffEffect { kind, .. })
|
||||
if matches!(kind, PotionSickness) =>
|
||||
{
|
||||
causes_potion_sickness = true;
|
||||
},
|
||||
|
||||
_ => {},
|
||||
}
|
||||
match effects {
|
||||
Effects::Any(effects) => {
|
||||
// Add the average of all effects.
|
||||
for effect in effects.iter() {
|
||||
let (add, red) = effect_healing_value(effect);
|
||||
value += add / effects.len() as f32;
|
||||
heal_multiplier_value *= 1.0 - red / effects.len() as f32;
|
||||
}
|
||||
},
|
||||
Effects::All(_) | Effects::One(_) => {
|
||||
for effect in effects.effects() {
|
||||
let (add, red) = effect_healing_value(effect);
|
||||
value += add;
|
||||
heal_multiplier_value *= 1.0 - red;
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
// Prefer non-potion sources of healing when under at least one stack of potion
|
||||
// sickness, or when incurring potion sickness is unnecessary
|
||||
if causes_potion_sickness && (heal_multiplier < 1.0 || relaxed) {
|
||||
if heal_multiplier_value < 1.0 && (heal_multiplier < 1.0 || relaxed) {
|
||||
value *= 0.1;
|
||||
}
|
||||
value as i32
|
||||
|
@ -51,7 +51,7 @@ pub fn create_character(
|
||||
.active_offhand(character_offhand.map(|x| Item::new_from_asset_expect(&x)))
|
||||
.build();
|
||||
let mut inventory = Inventory::with_loadout_humanoid(loadout);
|
||||
let stats = Stats::new(character_alias.to_string());
|
||||
let stats = Stats::new(character_alias.to_string(), body);
|
||||
let skill_set = SkillSet::default();
|
||||
// Default items for new characters
|
||||
inventory
|
||||
|
@ -1220,7 +1220,7 @@ fn handle_spawn(
|
||||
.state
|
||||
.create_npc(
|
||||
pos,
|
||||
comp::Stats::new(get_npc_name(id, npc::BodyType::from_body(body))),
|
||||
comp::Stats::new(get_npc_name(id, npc::BodyType::from_body(body)), body),
|
||||
comp::SkillSet::default(),
|
||||
Some(comp::Health::new(body, 0)),
|
||||
comp::Poise::new(body),
|
||||
@ -1294,7 +1294,7 @@ fn handle_spawn_training_dummy(
|
||||
|
||||
let body = comp::Body::Object(comp::object::Body::TrainingDummy);
|
||||
|
||||
let stats = comp::Stats::new("Training Dummy".to_string());
|
||||
let stats = comp::Stats::new("Training Dummy".to_string(), body);
|
||||
let skill_set = comp::SkillSet::default();
|
||||
let health = comp::Health::new(body, 0);
|
||||
let poise = comp::Poise::new(body);
|
||||
@ -3823,6 +3823,15 @@ fn handle_body(
|
||||
insert_or_replace_component(server, target, body.mass(), "mass")?;
|
||||
insert_or_replace_component(server, target, body.density(), "density")?;
|
||||
insert_or_replace_component(server, target, body.collider(), "collider")?;
|
||||
|
||||
if let Some(mut stat) = server
|
||||
.state
|
||||
.ecs_mut()
|
||||
.write_storage::<comp::Stats>()
|
||||
.get_mut(target)
|
||||
{
|
||||
stat.original_body = body;
|
||||
}
|
||||
Ok(())
|
||||
} else {
|
||||
Err(action.help_string())
|
||||
|
@ -1,5 +1,5 @@
|
||||
use hashbrown::HashSet;
|
||||
use rand::Rng;
|
||||
use rand::{seq::IteratorRandom, Rng};
|
||||
use specs::{join::Join, world::WorldExt, Builder, Entity as EcsEntity, WriteStorage};
|
||||
use tracing::{debug, error, warn};
|
||||
use vek::{Rgb, Vec3};
|
||||
@ -542,8 +542,20 @@ pub fn handle_inventory(server: &mut Server, entity: EcsEntity, manip: comp::Inv
|
||||
drop(inventories);
|
||||
|
||||
if let Some(effects) = maybe_effect {
|
||||
for effect in effects {
|
||||
state.apply_effect(entity, effect, None);
|
||||
match effects {
|
||||
item::Effects::Any(effects) => {
|
||||
if let Some(effect) = effects.into_iter().choose(&mut rand::thread_rng()) {
|
||||
state.apply_effect(entity, effect, None);
|
||||
}
|
||||
},
|
||||
item::Effects::All(effects) => {
|
||||
for effect in effects {
|
||||
state.apply_effect(entity, effect, None);
|
||||
}
|
||||
},
|
||||
item::Effects::One(effect) => {
|
||||
state.apply_effect(entity, effect, None);
|
||||
},
|
||||
}
|
||||
}
|
||||
if let Some(event) = event {
|
||||
@ -950,7 +962,10 @@ pub fn handle_inventory(server: &mut Server, entity: EcsEntity, manip: comp::Inv
|
||||
});
|
||||
},
|
||||
item::Throwable::TrainingDummy => {
|
||||
new_entity = new_entity.with(comp::Stats::new("Training Dummy".to_string()));
|
||||
new_entity = new_entity.with(comp::Stats::new(
|
||||
"Training Dummy".to_string(),
|
||||
Body::Object(common::comp::object::Body::TrainingDummy),
|
||||
));
|
||||
},
|
||||
};
|
||||
|
||||
|
@ -231,7 +231,7 @@ pub fn load_character_data(
|
||||
let pet = comp::Pet::new_from_database(
|
||||
NonZeroU64::new(db_pet.database_id as u64).unwrap(),
|
||||
);
|
||||
let pet_stats = comp::Stats::new(db_pet.name.to_owned());
|
||||
let pet_stats = comp::Stats::new(db_pet.name.to_owned(), pet_body);
|
||||
Some((pet, pet_body, pet_stats))
|
||||
} else {
|
||||
warn!(
|
||||
@ -259,10 +259,11 @@ pub fn load_character_data(
|
||||
|
||||
let (skill_set, skill_set_persistence_load_error) =
|
||||
convert_skill_set_from_database(&skill_group_data);
|
||||
let body = convert_body_from_database(&body_data.variant, &body_data.body_data)?;
|
||||
Ok((
|
||||
PersistedComponents {
|
||||
body: convert_body_from_database(&body_data.variant, &body_data.body_data)?,
|
||||
stats: convert_stats_from_database(character_data.alias),
|
||||
body,
|
||||
stats: convert_stats_from_database(character_data.alias, body),
|
||||
skill_set,
|
||||
inventory: convert_inventory_from_database_items(
|
||||
character_containers.inventory_container_id,
|
||||
|
@ -600,8 +600,8 @@ pub fn convert_character_from_database(character: &Character) -> common::charact
|
||||
}
|
||||
}
|
||||
|
||||
pub fn convert_stats_from_database(alias: String) -> Stats {
|
||||
let mut new_stats = Stats::empty();
|
||||
pub fn convert_stats_from_database(alias: String, body: Body) -> Stats {
|
||||
let mut new_stats = Stats::empty(body);
|
||||
new_stats.name = alias;
|
||||
new_stats
|
||||
}
|
||||
|
@ -356,7 +356,7 @@ impl StateExt for State {
|
||||
// TODO: some of these are required in order for the character_behavior system to
|
||||
// recognize a possesed airship; that system should be refactored to use `.maybe()`
|
||||
.with(comp::Energy::new(ship.into(), 0))
|
||||
.with(comp::Stats::new("Airship".to_string()))
|
||||
.with(comp::Stats::new("Airship".to_string(), body))
|
||||
.with(comp::SkillSet::default())
|
||||
.with(comp::ActiveAbilities::default())
|
||||
.with(comp::Combo::default());
|
||||
|
@ -454,7 +454,7 @@ impl NpcData {
|
||||
}
|
||||
|
||||
let name = name.unwrap_or_else(|| "Unnamed".to_string());
|
||||
let stats = comp::Stats::new(name);
|
||||
let stats = comp::Stats::new(name, body);
|
||||
|
||||
let skill_set = {
|
||||
let skillset_builder = SkillSetBuilder::default();
|
||||
|
@ -111,7 +111,8 @@ pub fn localize_chat_message(
|
||||
| BuffKind::Ensnared
|
||||
| BuffKind::Poisoned
|
||||
| BuffKind::Parried
|
||||
| BuffKind::PotionSickness => {
|
||||
| BuffKind::PotionSickness
|
||||
| BuffKind::Polymorphed(_) => {
|
||||
tracing::error!("Player was killed by a debuff that doesn't do damage!");
|
||||
"hud-outcome-mysterious"
|
||||
},
|
||||
|
@ -531,6 +531,15 @@ impl MusicMgr {
|
||||
soundtrack.tracks.push(track)
|
||||
}
|
||||
},
|
||||
_ => {
|
||||
for track in SoundtrackCollection::load_expect("voxygen.audio.soundtrack")
|
||||
.read()
|
||||
.tracks
|
||||
.clone()
|
||||
{
|
||||
soundtrack.tracks.push(track)
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -615,6 +624,7 @@ mod tests {
|
||||
"voxygen.audio.calendar.christmas.soundtrack",
|
||||
);
|
||||
},
|
||||
_ => {},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -754,6 +754,7 @@ image_ids! {
|
||||
debuff_poisoned_0: "voxygen.element.de_buffs.debuff_poisoned_0",
|
||||
debuff_parried_0: "voxygen.element.de_buffs.debuff_parried_0",
|
||||
debuff_potionsickness_0: "voxygen.element.de_buffs.debuff_potionsickness_0",
|
||||
debuff_polymorphed: "voxygen.element.de_buffs.debuff_polymorphed",
|
||||
|
||||
// Animation Frames
|
||||
// Buff Frame
|
||||
|
@ -4946,6 +4946,7 @@ pub fn get_buff_image(buff: BuffKind, imgs: &Imgs) -> conrod_core::image::Id {
|
||||
BuffKind::Poisoned => imgs.debuff_poisoned_0,
|
||||
BuffKind::Parried => imgs.debuff_parried_0,
|
||||
BuffKind::PotionSickness => imgs.debuff_potionsickness_0,
|
||||
BuffKind::Polymorphed(_) => imgs.debuff_polymorphed,
|
||||
}
|
||||
}
|
||||
|
||||
@ -4980,6 +4981,7 @@ pub fn get_buff_title(buff: BuffKind, localized_strings: &Localization) -> Cow<s
|
||||
BuffKind::Poisoned { .. } => localized_strings.get_msg("buff-title-poisoned"),
|
||||
BuffKind::Parried { .. } => localized_strings.get_msg("buff-title-parried"),
|
||||
BuffKind::PotionSickness { .. } => localized_strings.get_msg("buff-title-potionsickness"),
|
||||
BuffKind::Polymorphed { .. } => localized_strings.get_msg("buff-title-polymorphed"),
|
||||
}
|
||||
}
|
||||
|
||||
@ -5018,6 +5020,7 @@ pub fn get_buff_desc(buff: BuffKind, data: BuffData, localized_strings: &Localiz
|
||||
BuffKind::Poisoned { .. } => localized_strings.get_msg("buff-desc-poisoned"),
|
||||
BuffKind::Parried { .. } => localized_strings.get_msg("buff-desc-parried"),
|
||||
BuffKind::PotionSickness { .. } => localized_strings.get_msg("buff-desc-potionsickness"),
|
||||
BuffKind::Polymorphed { .. } => localized_strings.get_msg("buff-desc-polymorphed"),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -5,7 +5,7 @@ use common::{
|
||||
item::{
|
||||
armor::{Armor, ArmorKind, Protection},
|
||||
tool::{Hands, Tool, ToolKind},
|
||||
ItemDefinitionId, ItemDesc, ItemKind, MaterialKind, MaterialStatManifest,
|
||||
Effects, ItemDefinitionId, ItemDesc, ItemKind, MaterialKind, MaterialStatManifest,
|
||||
},
|
||||
BuffKind,
|
||||
},
|
||||
@ -112,7 +112,10 @@ pub fn stats_count(item: &dyn ItemDesc, msm: &MaterialStatManifest) -> usize {
|
||||
+ (item.num_slots() > 0) as usize
|
||||
},
|
||||
ItemKind::Tool(_) => 7,
|
||||
ItemKind::Consumable { effects, .. } => effects.len(),
|
||||
ItemKind::Consumable { effects, .. } => match effects {
|
||||
Effects::Any(_) | Effects::One(_) => 1,
|
||||
Effects::All(effects) => effects.len(),
|
||||
},
|
||||
ItemKind::ModularComponent { .. } => 7,
|
||||
_ => 0,
|
||||
}
|
||||
@ -138,108 +141,119 @@ pub fn line_count(item: &dyn ItemDesc, msm: &MaterialStatManifest, i18n: &Locali
|
||||
///
|
||||
/// FIXME: handle which effects should have description in `stats_count`
|
||||
/// to not waste space in item box
|
||||
pub fn consumable_desc(effects: &[Effect], i18n: &Localization) -> Vec<String> {
|
||||
pub fn consumable_desc(effects: &Effects, i18n: &Localization) -> Vec<String> {
|
||||
let mut descriptions = Vec::new();
|
||||
match effects {
|
||||
Effects::Any(_) => {
|
||||
descriptions.push(i18n.get_msg("buff-mysterious").into_owned());
|
||||
},
|
||||
Effects::All(_) | Effects::One(_) => {
|
||||
for effect in effects.effects() {
|
||||
let mut description = String::new();
|
||||
if let Effect::Buff(buff) = effect {
|
||||
let strength = buff.data.strength;
|
||||
let dur_secs = buff.data.duration.map(|d| d.0 as f32);
|
||||
let str_total = dur_secs.map_or(strength, |secs| strength * secs);
|
||||
|
||||
for effect in effects {
|
||||
let mut description = String::new();
|
||||
if let Effect::Buff(buff) = effect {
|
||||
let strength = buff.data.strength;
|
||||
let dur_secs = buff.data.duration.map(|d| d.0 as f32);
|
||||
let str_total = dur_secs.map_or(strength, |secs| strength * secs);
|
||||
let format_float =
|
||||
|input: f32| format!("{:.1}", input).trim_end_matches(".0").to_string();
|
||||
|
||||
let format_float =
|
||||
|input: f32| format!("{:.1}", input).trim_end_matches(".0").to_string();
|
||||
let buff_desc = match buff.kind {
|
||||
BuffKind::Saturation | BuffKind::Regeneration | BuffKind::Potion => i18n
|
||||
.get_msg_ctx("buff-stat-health", &i18n::fluent_args! {
|
||||
"str_total" => format_float(str_total),
|
||||
}),
|
||||
BuffKind::EnergyRegen => {
|
||||
i18n.get_msg_ctx("buff-stat-energy_regen", &i18n::fluent_args! {
|
||||
"str_total" => format_float(str_total),
|
||||
})
|
||||
},
|
||||
BuffKind::IncreaseMaxEnergy => {
|
||||
i18n.get_msg_ctx("buff-stat-increase_max_energy", &i18n::fluent_args! {
|
||||
"strength" => format_float(strength),
|
||||
})
|
||||
},
|
||||
BuffKind::IncreaseMaxHealth => {
|
||||
i18n.get_msg_ctx("buff-stat-increase_max_health", &i18n::fluent_args! {
|
||||
"strength" => format_float(strength),
|
||||
})
|
||||
},
|
||||
BuffKind::PotionSickness => {
|
||||
i18n.get_msg_ctx("buff-stat-potionsickness", &i18n::fluent_args! {
|
||||
"strength" => format_float(strength * 100.0),
|
||||
})
|
||||
},
|
||||
BuffKind::Invulnerability => i18n.get_msg("buff-stat-invulnerability"),
|
||||
BuffKind::Bleeding
|
||||
| BuffKind::Burning
|
||||
| BuffKind::CampfireHeal
|
||||
| BuffKind::Cursed
|
||||
| BuffKind::ProtectingWard
|
||||
| BuffKind::Crippled
|
||||
| BuffKind::Frenzied
|
||||
| BuffKind::Frozen
|
||||
| BuffKind::Wet
|
||||
| BuffKind::Ensnared
|
||||
| BuffKind::Poisoned
|
||||
| BuffKind::Hastened
|
||||
| BuffKind::Fortitude
|
||||
| BuffKind::Parried
|
||||
| BuffKind::Reckless
|
||||
| BuffKind::Polymorphed(_) => Cow::Borrowed(""),
|
||||
};
|
||||
|
||||
let buff_desc = match buff.kind {
|
||||
BuffKind::Saturation | BuffKind::Regeneration | BuffKind::Potion => i18n
|
||||
.get_msg_ctx("buff-stat-health", &i18n::fluent_args! {
|
||||
"str_total" => format_float(str_total),
|
||||
}),
|
||||
BuffKind::EnergyRegen => {
|
||||
i18n.get_msg_ctx("buff-stat-energy_regen", &i18n::fluent_args! {
|
||||
"str_total" => format_float(str_total),
|
||||
})
|
||||
},
|
||||
BuffKind::IncreaseMaxEnergy => {
|
||||
i18n.get_msg_ctx("buff-stat-increase_max_energy", &i18n::fluent_args! {
|
||||
"strength" => format_float(strength),
|
||||
})
|
||||
},
|
||||
BuffKind::IncreaseMaxHealth => {
|
||||
i18n.get_msg_ctx("buff-stat-increase_max_health", &i18n::fluent_args! {
|
||||
"strength" => format_float(strength),
|
||||
})
|
||||
},
|
||||
BuffKind::PotionSickness => {
|
||||
i18n.get_msg_ctx("buff-stat-potionsickness", &i18n::fluent_args! {
|
||||
"strength" => format_float(strength * 100.0),
|
||||
})
|
||||
},
|
||||
BuffKind::Invulnerability => i18n.get_msg("buff-stat-invulnerability"),
|
||||
BuffKind::Bleeding
|
||||
| BuffKind::Burning
|
||||
| BuffKind::CampfireHeal
|
||||
| BuffKind::Cursed
|
||||
| BuffKind::ProtectingWard
|
||||
| BuffKind::Crippled
|
||||
| BuffKind::Frenzied
|
||||
| BuffKind::Frozen
|
||||
| BuffKind::Wet
|
||||
| BuffKind::Ensnared
|
||||
| BuffKind::Poisoned
|
||||
| BuffKind::Hastened
|
||||
| BuffKind::Fortitude
|
||||
| BuffKind::Parried
|
||||
| BuffKind::Reckless => Cow::Borrowed(""),
|
||||
};
|
||||
write!(&mut description, "{}", buff_desc).unwrap();
|
||||
|
||||
write!(&mut description, "{}", buff_desc).unwrap();
|
||||
let dur_desc = if let Some(dur_secs) = dur_secs {
|
||||
match buff.kind {
|
||||
BuffKind::Saturation
|
||||
| BuffKind::Regeneration
|
||||
| BuffKind::EnergyRegen => {
|
||||
i18n.get_msg_ctx("buff-text-over_seconds", &i18n::fluent_args! {
|
||||
"dur_secs" => dur_secs
|
||||
})
|
||||
},
|
||||
BuffKind::IncreaseMaxEnergy
|
||||
| BuffKind::IncreaseMaxHealth
|
||||
| BuffKind::Invulnerability
|
||||
| BuffKind::PotionSickness
|
||||
| BuffKind::Polymorphed(_) => {
|
||||
i18n.get_msg_ctx("buff-text-for_seconds", &i18n::fluent_args! {
|
||||
"dur_secs" => dur_secs
|
||||
})
|
||||
},
|
||||
BuffKind::Bleeding
|
||||
| BuffKind::Burning
|
||||
| BuffKind::Potion
|
||||
| BuffKind::CampfireHeal
|
||||
| BuffKind::Cursed
|
||||
| BuffKind::ProtectingWard
|
||||
| BuffKind::Crippled
|
||||
| BuffKind::Frenzied
|
||||
| BuffKind::Frozen
|
||||
| BuffKind::Wet
|
||||
| BuffKind::Ensnared
|
||||
| BuffKind::Poisoned
|
||||
| BuffKind::Hastened
|
||||
| BuffKind::Fortitude
|
||||
| BuffKind::Parried
|
||||
| BuffKind::Reckless => Cow::Borrowed(""),
|
||||
}
|
||||
} else if let BuffKind::Saturation
|
||||
| BuffKind::Regeneration
|
||||
| BuffKind::EnergyRegen = buff.kind
|
||||
{
|
||||
i18n.get_msg("buff-text-every_second")
|
||||
} else {
|
||||
Cow::Borrowed("")
|
||||
};
|
||||
|
||||
let dur_desc = if let Some(dur_secs) = dur_secs {
|
||||
match buff.kind {
|
||||
BuffKind::Saturation | BuffKind::Regeneration | BuffKind::EnergyRegen => i18n
|
||||
.get_msg_ctx("buff-text-over_seconds", &i18n::fluent_args! {
|
||||
"dur_secs" => dur_secs
|
||||
}),
|
||||
BuffKind::IncreaseMaxEnergy
|
||||
| BuffKind::IncreaseMaxHealth
|
||||
| BuffKind::Invulnerability
|
||||
| BuffKind::PotionSickness => {
|
||||
i18n.get_msg_ctx("buff-text-for_seconds", &i18n::fluent_args! {
|
||||
"dur_secs" => dur_secs
|
||||
})
|
||||
},
|
||||
BuffKind::Bleeding
|
||||
| BuffKind::Burning
|
||||
| BuffKind::Potion
|
||||
| BuffKind::CampfireHeal
|
||||
| BuffKind::Cursed
|
||||
| BuffKind::ProtectingWard
|
||||
| BuffKind::Crippled
|
||||
| BuffKind::Frenzied
|
||||
| BuffKind::Frozen
|
||||
| BuffKind::Wet
|
||||
| BuffKind::Ensnared
|
||||
| BuffKind::Poisoned
|
||||
| BuffKind::Hastened
|
||||
| BuffKind::Fortitude
|
||||
| BuffKind::Parried
|
||||
| BuffKind::Reckless => Cow::Borrowed(""),
|
||||
write!(&mut description, " {}", dur_desc).unwrap();
|
||||
}
|
||||
} else if let BuffKind::Saturation | BuffKind::Regeneration | BuffKind::EnergyRegen =
|
||||
buff.kind
|
||||
{
|
||||
i18n.get_msg("buff-text-every_second")
|
||||
} else {
|
||||
Cow::Borrowed("")
|
||||
};
|
||||
|
||||
write!(&mut description, " {}", dur_desc).unwrap();
|
||||
}
|
||||
descriptions.push(description);
|
||||
descriptions.push(description);
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
descriptions
|
||||
}
|
||||
|
||||
|
@ -1375,6 +1375,41 @@ impl ParticleMgr {
|
||||
},
|
||||
);
|
||||
},
|
||||
BuffKind::Polymorphed(_) => {
|
||||
let mut multiplicity = 0;
|
||||
// Only show particles for polymorph at the beginning, after the
|
||||
// drinking animation finishes
|
||||
if buff_ids.0
|
||||
.iter()
|
||||
.filter_map(|id| buffs.buffs.get(id))
|
||||
.any(|buff| {
|
||||
matches!(buff.elapsed(Time(time)), dur if (0.1..=0.3).contains(&dur.0))
|
||||
})
|
||||
{
|
||||
multiplicity = 1;
|
||||
}
|
||||
self.particles.resize_with(
|
||||
self.particles.len()
|
||||
+ multiplicity
|
||||
* self.scheduler.heartbeats(Duration::from_millis(3)) as usize,
|
||||
|| {
|
||||
let start_pos = pos + Vec3::unit_z() * body.eye_height() / 2.0;
|
||||
let end_pos = start_pos
|
||||
+ Vec3::<f32>::zero()
|
||||
.map(|_| rng.gen_range(-1.0..1.0))
|
||||
.normalized()
|
||||
* 5.0;
|
||||
|
||||
Particle::new_directed(
|
||||
Duration::from_secs(2),
|
||||
time,
|
||||
ParticleMode::Explosion,
|
||||
start_pos,
|
||||
end_pos,
|
||||
)
|
||||
},
|
||||
)
|
||||
},
|
||||
_ => {},
|
||||
}
|
||||
}
|
||||
|
@ -171,6 +171,10 @@ pub fn spawn_manifest() -> Vec<(&'static str, DensityFn)> {
|
||||
"world.wildlife.spawn.calendar.halloween.tundra.core",
|
||||
|c, _col| close(c.temp, CONFIG.snow_temp, 0.15) * BASE_DENSITY * 0.5,
|
||||
),
|
||||
(
|
||||
"world.wildlife.spawn.calendar.april_fools.tundra.core",
|
||||
|c, _col| close(c.temp, CONFIG.snow_temp, 0.15) * BASE_DENSITY * 0.5,
|
||||
),
|
||||
// Snowy animals
|
||||
("world.wildlife.spawn.tundra.snow", |c, col| {
|
||||
close(c.temp, CONFIG.snow_temp, 0.3) * BASE_DENSITY * col.snow_cover as i32 as f32 * 1.0
|
||||
@ -194,6 +198,15 @@ pub fn spawn_manifest() -> Vec<(&'static str, DensityFn)> {
|
||||
* 1.0
|
||||
},
|
||||
),
|
||||
(
|
||||
"world.wildlife.spawn.calendar.april_fools.tundra.snow",
|
||||
|c, col| {
|
||||
close(c.temp, CONFIG.snow_temp, 0.3)
|
||||
* BASE_DENSITY
|
||||
* col.snow_cover as i32 as f32
|
||||
* 1.0
|
||||
},
|
||||
),
|
||||
// Forest animals
|
||||
("world.wildlife.spawn.tundra.forest", |c, col| {
|
||||
close(c.temp, CONFIG.snow_temp, 0.3) * col.tree_density * BASE_DENSITY * 1.4
|
||||
@ -207,6 +220,10 @@ pub fn spawn_manifest() -> Vec<(&'static str, DensityFn)> {
|
||||
"world.wildlife.spawn.calendar.halloween.tundra.forest",
|
||||
|c, col| close(c.temp, CONFIG.snow_temp, 0.3) * col.tree_density * BASE_DENSITY * 1.4,
|
||||
),
|
||||
(
|
||||
"world.wildlife.spawn.calendar.april_fools.tundra.forest",
|
||||
|c, col| close(c.temp, CONFIG.snow_temp, 0.3) * col.tree_density * BASE_DENSITY * 1.4,
|
||||
),
|
||||
// **Taiga**
|
||||
// Forest core animals
|
||||
("world.wildlife.spawn.taiga.core_forest", |c, col| {
|
||||
@ -225,6 +242,12 @@ pub fn spawn_manifest() -> Vec<(&'static str, DensityFn)> {
|
||||
close(c.temp, CONFIG.snow_temp + 0.2, 0.2) * col.tree_density * BASE_DENSITY * 0.4
|
||||
},
|
||||
),
|
||||
(
|
||||
"world.wildlife.spawn.calendar.april_fools.taiga.core",
|
||||
|c, col| {
|
||||
close(c.temp, CONFIG.snow_temp + 0.2, 0.2) * col.tree_density * BASE_DENSITY * 0.4
|
||||
},
|
||||
),
|
||||
// Core animals
|
||||
("world.wildlife.spawn.taiga.core", |c, _col| {
|
||||
close(c.temp, CONFIG.snow_temp + 0.2, 0.2) * BASE_DENSITY * 1.0
|
||||
@ -276,6 +299,15 @@ pub fn spawn_manifest() -> Vec<(&'static str, DensityFn)> {
|
||||
* 4.0
|
||||
},
|
||||
),
|
||||
(
|
||||
"world.wildlife.spawn.calendar.april_fools.temperate.rainforest",
|
||||
|c, _col| {
|
||||
close(c.temp, CONFIG.temperate_temp + 0.1, 0.6)
|
||||
* close(c.humidity, CONFIG.forest_hum, 0.6)
|
||||
* BASE_DENSITY
|
||||
* 4.0
|
||||
},
|
||||
),
|
||||
// Water animals
|
||||
("world.wildlife.spawn.temperate.water", |c, col| {
|
||||
close(c.temp, CONFIG.temperate_temp, 1.0) * col.tree_density * BASE_DENSITY * 5.0
|
||||
@ -305,6 +337,15 @@ pub fn spawn_manifest() -> Vec<(&'static str, DensityFn)> {
|
||||
* 8.0
|
||||
},
|
||||
),
|
||||
(
|
||||
"world.wildlife.spawn.calendar.april_fools.jungle.area",
|
||||
|c, _col| {
|
||||
close(c.temp, CONFIG.tropical_temp + 0.2, 0.3)
|
||||
* close(c.humidity, CONFIG.jungle_hum, 0.2)
|
||||
* BASE_DENSITY
|
||||
* 8.0
|
||||
},
|
||||
),
|
||||
// **Tropical**
|
||||
// Rare river animals
|
||||
("world.wildlife.spawn.tropical.river_rare", |_c, col| {
|
||||
@ -361,6 +402,15 @@ pub fn spawn_manifest() -> Vec<(&'static str, DensityFn)> {
|
||||
* 2.0
|
||||
},
|
||||
),
|
||||
(
|
||||
"world.wildlife.spawn.calendar.april_fools.tropical.rainforest",
|
||||
|c, _col| {
|
||||
close(c.temp, CONFIG.tropical_temp + 0.1, 0.4)
|
||||
* close(c.humidity, CONFIG.desert_hum, 0.4)
|
||||
* BASE_DENSITY
|
||||
* 2.0
|
||||
},
|
||||
),
|
||||
// Rock animals
|
||||
("world.wildlife.spawn.tropical.rock", |c, col| {
|
||||
close(c.temp, CONFIG.tropical_temp + 0.1, 0.5) * col.rock_density * BASE_DENSITY * 5.0
|
||||
|
Loading…
Reference in New Issue
Block a user