feat(vf): add PotionItem and BrewRecipe
This commit is contained in:
1 parent
5d7081ff32
commit
f1f8b53b0c
1 file changed
+149
@@ -0,0 +1,149 @@
|
||||
#pragma once
|
||||
|
||||
#include <array>
|
||||
#include <cstdint>
|
||||
#include <vector>
|
||||
|
||||
#include "Effect.h"
|
||||
|
||||
namespace vf {
|
||||
|
||||
// A stand holds three bottles, one ingredient stack and a blaze powder fuel bar.
|
||||
// Every completed brew converts all three bottles at once and spends a single
|
||||
// unit of ingredient and a single unit of fuel.
|
||||
constexpr int brewingBottleSlots = 3;
|
||||
constexpr int brewDurationTicks = 400;
|
||||
constexpr int brewsPerBlazePowder = 20;
|
||||
|
||||
// Ordering is load bearing: the profile table in Brewing.cpp is indexed by this
|
||||
// enum and static_asserts against Count.
|
||||
enum class PotionKind : uint8_t {
|
||||
Water,
|
||||
Mundane,
|
||||
Thick,
|
||||
Awkward,
|
||||
Healing,
|
||||
Harming,
|
||||
Regeneration,
|
||||
Poison,
|
||||
Swiftness,
|
||||
Slowness,
|
||||
Leaping,
|
||||
Strength,
|
||||
Weakness,
|
||||
FireResistance,
|
||||
WaterBreathing,
|
||||
NightVision,
|
||||
Invisibility,
|
||||
Count
|
||||
};
|
||||
|
||||
struct PotionItem {
|
||||
// Gunpowder turns a drinkable into a splash. Dragon breath turns a splash
|
||||
// into a lingering cloud, which the stand itself cannot do: see
|
||||
// catalogBrewStep in PotionCatalog.h.
|
||||
enum class Form : uint8_t { Drinkable, Splash, Lingering };
|
||||
|
||||
PotionKind kind = PotionKind::Water;
|
||||
Form form = Form::Drinkable;
|
||||
// Glowstone raises the level and shortens the potion, redstone lengthens it
|
||||
// at level one. The two are mutually exclusive, the later one wins.
|
||||
bool upgraded = false;
|
||||
bool extended = false;
|
||||
|
||||
bool operator==(const PotionItem& other) const {
|
||||
return kind == other.kind && form == other.form && upgraded == other.upgraded &&
|
||||
extended == other.extended;
|
||||
}
|
||||
bool operator!=(const PotionItem& other) const { return !(*this == other); }
|
||||
};
|
||||
|
||||
struct BrewRecipe {
|
||||
enum class Ingredient : uint8_t {
|
||||
None,
|
||||
NetherWart,
|
||||
Redstone,
|
||||
Glowstone,
|
||||
Gunpowder,
|
||||
DragonBreath,
|
||||
FermentedSpiderEye,
|
||||
SpiderEye,
|
||||
GhastTear,
|
||||
Sugar,
|
||||
RabbitFoot,
|
||||
BlazePowder,
|
||||
GlisteringMelon,
|
||||
MagmaCream,
|
||||
PufferFish,
|
||||
GoldenCarrot,
|
||||
Count
|
||||
};
|
||||
|
||||
PotionKind input = PotionKind::Water;
|
||||
Ingredient ingredient = Ingredient::None;
|
||||
PotionKind output = PotionKind::Water;
|
||||
};
|
||||
|
||||
struct BrewingSlot {
|
||||
PotionItem potion;
|
||||
bool occupied = false;
|
||||
};
|
||||
|
||||
struct BrewingStandState {
|
||||
std::array<BrewingSlot, brewingBottleSlots> bottles{};
|
||||
BrewRecipe::Ingredient ingredient = BrewRecipe::Ingredient::None;
|
||||
int ingredientCount = 0;
|
||||
// Measured in brews, not in items: addFuel multiplies by brewsPerBlazePowder.
|
||||
int fuel = 0;
|
||||
int progressTicks = 0;
|
||||
bool brewing = false;
|
||||
};
|
||||
|
||||
// Every kind-changing recipe the stand knows. Modifier ingredients (glowstone,
|
||||
// redstone, gunpowder) are not recipes and do not appear here.
|
||||
const std::vector<BrewRecipe>& brewRecipes();
|
||||
|
||||
// Resolves one ingredient against one bottle. A kind change wipes the glowstone
|
||||
// and redstone modifiers but keeps the form. Sets `changed` to false when the
|
||||
// ingredient does nothing to that bottle, in which case the input is returned
|
||||
// unaltered.
|
||||
PotionItem brewResult(const PotionItem& base, BrewRecipe::Ingredient ingredient, bool& changed);
|
||||
|
||||
// Fails when the slot index is out of range or already holds a bottle.
|
||||
bool setBottle(BrewingStandState& stand, int slot, const PotionItem& potion);
|
||||
PotionItem takeBottle(BrewingStandState& stand, int slot, bool& taken);
|
||||
|
||||
// Stacks onto the existing ingredient when it matches, refuses a different one
|
||||
// while the current stack is not empty.
|
||||
bool setIngredient(BrewingStandState& stand, BrewRecipe::Ingredient ingredient, int count);
|
||||
bool addFuel(BrewingStandState& stand, int blazePowderCount);
|
||||
|
||||
// True when fuel, ingredient and at least one bottle that the ingredient would
|
||||
// actually change are all present.
|
||||
bool canBrew(const BrewingStandState& stand);
|
||||
|
||||
// One tick of the stand. Returns true on the tick the brew completes, which is
|
||||
// the brewDurationTicks-th consecutive tick with canBrew holding. Any tick where
|
||||
// canBrew fails resets the progress bar to zero.
|
||||
bool tickBrewing(BrewingStandState& stand);
|
||||
|
||||
// Water, mundane, thick and awkward carry no effect.
|
||||
bool potionHasEffect(const PotionItem& potion);
|
||||
|
||||
// The effect a bottle would apply, with the level and duration its glowstone or
|
||||
// redstone modifier calls for. Returns an EffectKind::Count instance for the
|
||||
// four effectless kinds.
|
||||
EffectInstance potionEffect(const PotionItem& potion);
|
||||
|
||||
// Drinkable form only. Returns whatever applyEffect reports.
|
||||
bool drinkPotion(EffectSet& target, const PotionItem& potion);
|
||||
|
||||
// Linear falloff from the impact point, clamped to 0..1.
|
||||
float splashPotency(float distance, float radius);
|
||||
|
||||
// Splash form only. Instant effects scale their magnitude by the potency, timed
|
||||
// effects keep their level and lose duration: three quarters at the impact
|
||||
// point, less further out.
|
||||
bool splashPotion(EffectSet& target, const PotionItem& potion, float distance, float radius);
|
||||
|
||||
} // namespace vf
|
||||
Reference in new issue
Block a user