feat(vf): add WitherFightConfig and WitherTarget to Boss
This commit is contained in:
1 parent
76f2be284b
commit
5d7081ff32
1 file changed
+128
@@ -158,3 +158,131 @@ public:
|
||||
DragonFight(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
|
||||
Reference in new issue
Block a user