feat: add distanceBetween and crystalCenter
This commit is contained in:
1 parent
bdad4a344b
commit
1748324d41
1 file changed
+156
@@ -0,0 +1,156 @@
|
|||||||
|
#include "vf/Boss.h"
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
#include <cmath>
|
||||||
|
#include <utility>
|
||||||
|
|
||||||
|
namespace vf {
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
constexpr float fullTurn = 6.2831853f;
|
||||||
|
|
||||||
|
float distanceBetween(const Vec3& a, const Vec3& b) { return length(a - b); }
|
||||||
|
|
||||||
|
std::unique_ptr<BehaviorNode> cond(const char* name, BehaviorPredicate predicate) {
|
||||||
|
return std::unique_ptr<BehaviorNode>(new ConditionNode(name, std::move(predicate)));
|
||||||
|
}
|
||||||
|
|
||||||
|
std::unique_ptr<BehaviorNode> act(const char* name, BehaviorAction fn) {
|
||||||
|
return std::unique_ptr<BehaviorNode>(new ActionNode(name, std::move(fn)));
|
||||||
|
}
|
||||||
|
|
||||||
|
std::unique_ptr<SequenceNode> seq(const char* name) {
|
||||||
|
return std::unique_ptr<SequenceNode>(new SequenceNode(name));
|
||||||
|
}
|
||||||
|
|
||||||
|
std::unique_ptr<SelectorNode> sel(const char* name) {
|
||||||
|
return std::unique_ptr<SelectorNode>(new SelectorNode(name));
|
||||||
|
}
|
||||||
|
|
||||||
|
std::unique_ptr<BehaviorNode> gated(const char* name, std::unique_ptr<BehaviorNode> child,
|
||||||
|
int ticks) {
|
||||||
|
return std::unique_ptr<BehaviorNode>(new CooldownNode(name, std::move(child), ticks));
|
||||||
|
}
|
||||||
|
|
||||||
|
std::unique_ptr<BehaviorNode> bounded(const char* name, std::unique_ptr<BehaviorNode> child,
|
||||||
|
int ticks) {
|
||||||
|
return std::unique_ptr<BehaviorNode>(new TimeLimitNode(name, std::move(child), ticks));
|
||||||
|
}
|
||||||
|
|
||||||
|
Vec3 crystalCenter(const Vec3i& cell) {
|
||||||
|
return {static_cast<float>(cell.x) + 0.5f, static_cast<float>(cell.y) + 0.5f,
|
||||||
|
static_cast<float>(cell.z) + 0.5f};
|
||||||
|
}
|
||||||
|
|
||||||
|
Vec3i witherOffset(const Vec3i& base, int along, int up, bool alongX) {
|
||||||
|
return alongX ? Vec3i{base.x + along, base.y + up, base.z}
|
||||||
|
: Vec3i{base.x, base.y + up, base.z + along};
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
const char* bossKindName(BossKind kind) {
|
||||||
|
switch (kind) {
|
||||||
|
case BossKind::EnderDragon: return "enderDragon";
|
||||||
|
case BossKind::Wither: return "wither";
|
||||||
|
case BossKind::Count: break;
|
||||||
|
}
|
||||||
|
return "unknown";
|
||||||
|
}
|
||||||
|
|
||||||
|
const char* bossPhaseName(BossPhase phase) {
|
||||||
|
switch (phase) {
|
||||||
|
case BossPhase::Dormant: return "dormant";
|
||||||
|
case BossPhase::Circling: return "circling";
|
||||||
|
case BossPhase::Charging: return "charging";
|
||||||
|
case BossPhase::Breathing: return "breathing";
|
||||||
|
case BossPhase::Perching: return "perching";
|
||||||
|
case BossPhase::Summoning: return "summoning";
|
||||||
|
case BossPhase::Explosive: return "explosive";
|
||||||
|
case BossPhase::Ranged: return "ranged";
|
||||||
|
case BossPhase::Armored: return "armored";
|
||||||
|
case BossPhase::Dying: return "dying";
|
||||||
|
case BossPhase::Defeated: return "defeated";
|
||||||
|
case BossPhase::Count: break;
|
||||||
|
}
|
||||||
|
return "unknown";
|
||||||
|
}
|
||||||
|
|
||||||
|
int BossBar::notchCount() const {
|
||||||
|
switch (style) {
|
||||||
|
case BossBarStyle::Solid: return 1;
|
||||||
|
case BossBarStyle::Notched6: return 6;
|
||||||
|
case BossBarStyle::Notched10: return 10;
|
||||||
|
case BossBarStyle::Notched12: return 12;
|
||||||
|
case BossBarStyle::Notched20: return 20;
|
||||||
|
case BossBarStyle::Count: break;
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int BossBar::filledNotches() const {
|
||||||
|
float exact = progress * static_cast<float>(notchCount());
|
||||||
|
int whole = static_cast<int>(std::floor(exact + 1e-4f));
|
||||||
|
return std::max(0, std::min(notchCount(), whole));
|
||||||
|
}
|
||||||
|
|
||||||
|
int BossBar::percent() const {
|
||||||
|
return static_cast<int>(std::floor(progress * 100.0f + 0.5f));
|
||||||
|
}
|
||||||
|
|
||||||
|
void BossBar::setFromHealth(float health, float maxHealth) {
|
||||||
|
if (maxHealth <= 0.0f) {
|
||||||
|
progress = 0.0f;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
float fraction = health / maxHealth;
|
||||||
|
progress = std::max(0.0f, std::min(1.0f, fraction));
|
||||||
|
}
|
||||||
|
|
||||||
|
void BossState::enterPhase(BossPhase next) {
|
||||||
|
if (phase == next) return;
|
||||||
|
phase = next;
|
||||||
|
phaseTicks = 0;
|
||||||
|
++phaseChanges;
|
||||||
|
}
|
||||||
|
|
||||||
|
float BossState::healthFraction() const {
|
||||||
|
if (maxHealth <= 0.0f) return 0.0f;
|
||||||
|
return health / maxHealth;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<CrystalNode> crystalsFromPillars(const std::vector<ObsidianPillar>& pillars) {
|
||||||
|
std::vector<CrystalNode> nodes;
|
||||||
|
nodes.reserve(pillars.size());
|
||||||
|
for (const ObsidianPillar& pillar : pillars) {
|
||||||
|
CrystalNode node;
|
||||||
|
node.pillarBase = pillar.base;
|
||||||
|
node.pillarHeight = pillar.height;
|
||||||
|
node.position = {pillar.base.x, pillar.base.y + pillar.height + 1, pillar.base.z};
|
||||||
|
node.caged = pillar.crowned;
|
||||||
|
node.cageIntact = pillar.crowned;
|
||||||
|
nodes.push_back(node);
|
||||||
|
}
|
||||||
|
return nodes;
|
||||||
|
}
|
||||||
|
|
||||||
|
DragonFight::DragonFight(const EndGenerator& end, uint32_t seed, const DragonFightConfig& config)
|
||||||
|
: cfg(config) {
|
||||||
|
boss.kind = BossKind::EnderDragon;
|
||||||
|
boss.maxHealth = cfg.maxHealth;
|
||||||
|
boss.health = cfg.maxHealth;
|
||||||
|
boss.rng = seed != 0u ? seed : 0x51ed270bu;
|
||||||
|
boss.phase = BossPhase::Circling;
|
||||||
|
boss.bar.title = "Ender Dragon";
|
||||||
|
boss.bar.color = BossBarColor::Pink;
|
||||||
|
boss.bar.style = BossBarStyle::Notched10;
|
||||||
|
boss.bar.visible = true;
|
||||||
|
boss.bar.setFromHealth(boss.health, boss.maxHealth);
|
||||||
|
|
||||||
|
pillarCrystals = crystalsFromPillars(end.pillars());
|
||||||
|
|
||||||
|
int surface = end.surfaceHeight(0, 0);
|
||||||
|
portal = {0.5f, static_cast<float>(surface), 0.5f};
|
||||||
|
eggCell = {0, surface + 1, 0};
|
||||||
|
|
||||||
Reference in new issue
Block a user