feat(vf): add WitherFightConfig and WitherTarget to Boss

This commit is contained in:
dualfroz committed 2026-09-01 17:36:12 +02:00
1 parent 76f2be284b
commit 5d7081ff32
1 file changed
+128
+128
View File
@@ -158,3 +158,131 @@ public:
DragonFight(DragonFight&&) = delete; DragonFight(DragonFight&&) = delete;
DragonFight& operator=(DragonFight&&) = delete; DragonFight& operator=(DragonFight&&) = delete;
BossTickReport tick(const DragonPlayerInput& input);
const BossState& state() const { return boss; }
const DragonFightConfig& settings() const { return cfg; }
const std::vector<CrystalNode>& crystals() const { return pillarCrystals; }
int aliveCrystalCount() const;
// Taken from the End generator: the fight orbits and perches on the real
// exit portal column, not on an invented origin.
Vec3 portalCenter() const { return portal; }
bool exitPortalOpen() const { return portalOpen; }
bool dragonEggDropped() const { return eggDropped; }
Vec3i eggPosition() const { return eggCell; }
const BehaviorTree& brain() const { return tree; }
const BehaviorContext& context() const { return ctx; }
// Writes the reward the fight earned: the real End exit portal from
// EndGen. Refuses while the dragon still lives.
bool placeVictoryStructures(World& world, const EndGenerator& end) const;
private:
void buildTree();
int resolvePlayerShot(const DragonPlayerInput& input);
void applyPlayerMelee(const DragonPlayerInput& input);
float applyCrystalHealing();
DragonFightConfig cfg;
BossState boss;
std::vector<CrystalNode> pillarCrystals;
BehaviorTree tree;
BehaviorContext ctx;
DragonPlayerInput lastInput;
Vec3 portal;
Vec3i eggCell;
bool portalOpen = false;
bool eggDropped = false;
float damageThisTick = 0.0f;
};
struct WitherFightConfig {
float maxHealth = 300.0f;
int summonTicks = 220;
float summonBlastRadius = 8.0f;
float summonBlastDamage = 12.0f;
float armorThreshold = 0.5f;
float projectileDamage = 5.0f;
float projectileRange = 32.0f;
int projectileCooldownTicks = 20;
int minionCooldownTicks = 100;
int maxMinions = 3;
float minionSpawnRange = 6.0f;
float armoredRegenPerTick = 0.06f;
float moveStep = 0.35f;
float minTargetDistance = 6.0f;
};
struct WitherTarget {
Vec3 position;
float health = 20.0f;
bool alive = true;
};
struct BossMinion {
Vec3 position;
float health = 6.0f;
bool alive = true;
long long spawnedTick = 0;
};
struct WitherHit {
float amount = 0.0f;
bool projectile = false;
};
// The block pattern that calls the wither: a soul sand T topped with three
// heads, readable along either horizontal axis.
Block witherBaseBlock();
Block witherHeadBlock();
bool witherPatternAt(const World& world, const Vec3i& baseCell, bool alongX);
bool findWitherPattern(const World& world, const Vec3i& baseCell, bool& outAlongX);
void consumeWitherPattern(World& world, const Vec3i& baseCell, bool alongX);
// Summons out of a block pattern, blasts everything around it on arrival, then
// hunts the nearest living target. Below half health it armours up: projectiles
// stop landing entirely and it starts regenerating and calling minions.
class WitherFight {
public:
explicit WitherFight(uint32_t seed, const WitherFightConfig& config = {});
WitherFight(const WitherFight&) = delete;
WitherFight& operator=(const WitherFight&) = delete;
WitherFight(WitherFight&&) = delete;
WitherFight& operator=(WitherFight&&) = delete;
void begin(const Vec3& spawnPosition);
// Consumes the pattern in the world and starts the fight at its centre.
bool summonFromWorld(World& world, const Vec3i& baseCell);
BossTickReport tick(const std::vector<WitherHit>& incoming,
std::vector<WitherTarget>& targets);
const BossState& state() const { return boss; }
const WitherFightConfig& settings() const { return cfg; }
const std::vector<BossMinion>& minions() const { return summoned; }
bool armored() const { return boss.phase == BossPhase::Armored; }
int aliveMinionCount() const;
const BehaviorTree& brain() const { return tree; }
const BehaviorContext& context() const { return ctx; }
private:
void buildTree();
float applyIncoming(const std::vector<WitherHit>& incoming);
int nearestAliveTarget() const;
WitherFightConfig cfg;
BossState boss;
std::vector<BossMinion> summoned;
BehaviorTree tree;
BehaviorContext ctx;
std::vector<WitherTarget>* activeTargets = nullptr;
float damageThisTick = 0.0f;
float healedThisTick = 0.0f;
int minionsThisTick = 0;
};
} // namespace vf