feat: add straightDistance and groundAndRoomFit
This commit is contained in:
1 parent
fea440d31f
commit
ebcace7837
1 file changed
+160
@@ -0,0 +1,160 @@
|
|||||||
|
#include "vf/Spawning.h"
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
#include <cmath>
|
||||||
|
|
||||||
|
#include "vf/Effect.h"
|
||||||
|
|
||||||
|
namespace vf {
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
constexpr int nightSkyLightPenalty = 11;
|
||||||
|
|
||||||
|
float straightDistance(const Vec3& a, const Vec3& b) {
|
||||||
|
Vec3 delta = a - b;
|
||||||
|
return length(delta);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool groundAndRoomFit(const SpawnRule& rule, const SpawnEnvironment& env, const Vec3i& cell) {
|
||||||
|
Block ground = env.world->blockAt(cell.x, cell.y - 1, cell.z);
|
||||||
|
if (!isSolid(ground)) return false;
|
||||||
|
if (!rule.allowsGround(ground)) return false;
|
||||||
|
return hasSpawnRoom(*env.world, cell, rule.requiredHeadroom);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool lightFits(const SpawnRule& rule, const SpawnEnvironment& env, const Vec3i& cell) {
|
||||||
|
int blockLight = env.blockLightAt(cell);
|
||||||
|
int skyLight = env.skyLightAt(cell);
|
||||||
|
if (blockLight > rule.maxBlockLight) return false;
|
||||||
|
if (skyLight > rule.maxSkyLight) return false;
|
||||||
|
if (blockLight < rule.minBlockLight) return false;
|
||||||
|
if (skyLight < rule.minSkyLight) return false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
SpawnRule makeHostileRule(Species species, int packMin, int packMax) {
|
||||||
|
SpawnRule rule;
|
||||||
|
rule.species = species;
|
||||||
|
rule.category = SpawnCategory::Hostile;
|
||||||
|
rule.dimension = DimensionId::Overworld;
|
||||||
|
rule.maxBlockLight = 7;
|
||||||
|
rule.maxSkyLight = 7;
|
||||||
|
rule.minY = 1;
|
||||||
|
rule.maxY = 127;
|
||||||
|
rule.requiredHeadroom = 2;
|
||||||
|
rule.dayAllowed = false;
|
||||||
|
rule.nightAllowed = true;
|
||||||
|
rule.packMin = packMin;
|
||||||
|
rule.packMax = packMax;
|
||||||
|
rule.packSpread = 3;
|
||||||
|
rule.weight = 10;
|
||||||
|
rule.minPlayerDistance = 24.0f;
|
||||||
|
rule.maxPlayerDistance = 128.0f;
|
||||||
|
return rule;
|
||||||
|
}
|
||||||
|
|
||||||
|
SpawnRule makePassiveRule(Species species, int packMin, int packMax,
|
||||||
|
std::vector<BiomeKind> biomeList) {
|
||||||
|
SpawnRule rule;
|
||||||
|
rule.species = species;
|
||||||
|
rule.category = SpawnCategory::Passive;
|
||||||
|
rule.dimension = DimensionId::Overworld;
|
||||||
|
rule.minBlockLight = 0;
|
||||||
|
rule.minSkyLight = 9;
|
||||||
|
rule.maxBlockLight = 15;
|
||||||
|
rule.maxSkyLight = 15;
|
||||||
|
rule.minY = 48;
|
||||||
|
rule.maxY = 127;
|
||||||
|
rule.groundBlocks = {Block::Grass};
|
||||||
|
rule.requiredHeadroom = 2;
|
||||||
|
rule.biomes = std::move(biomeList);
|
||||||
|
rule.dayAllowed = true;
|
||||||
|
rule.nightAllowed = true;
|
||||||
|
rule.packMin = packMin;
|
||||||
|
rule.packMax = packMax;
|
||||||
|
rule.packSpread = 4;
|
||||||
|
rule.weight = 12;
|
||||||
|
rule.minPlayerDistance = 12.0f;
|
||||||
|
rule.maxPlayerDistance = 96.0f;
|
||||||
|
return rule;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
const char* spawnCategoryName(SpawnCategory category) {
|
||||||
|
switch (category) {
|
||||||
|
case SpawnCategory::Hostile: return "hostile";
|
||||||
|
case SpawnCategory::Passive: return "passive";
|
||||||
|
case SpawnCategory::Water: return "water";
|
||||||
|
case SpawnCategory::Ambient: return "ambient";
|
||||||
|
case SpawnCategory::Count: break;
|
||||||
|
}
|
||||||
|
return "unknown";
|
||||||
|
}
|
||||||
|
|
||||||
|
SpawnCategory categoryForSpecies(Species species) {
|
||||||
|
return isHostile(species) ? SpawnCategory::Hostile : SpawnCategory::Passive;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char* spawnDenialName(SpawnDenial denial) {
|
||||||
|
switch (denial) {
|
||||||
|
case SpawnDenial::None: return "none";
|
||||||
|
case SpawnDenial::CategoryCapReached: return "categoryCapReached";
|
||||||
|
case SpawnDenial::WrongDimension: return "wrongDimension";
|
||||||
|
case SpawnDenial::WrongBiome: return "wrongBiome";
|
||||||
|
case SpawnDenial::WrongTimeOfDay: return "wrongTimeOfDay";
|
||||||
|
case SpawnDenial::HeightOutOfRange: return "heightOutOfRange";
|
||||||
|
case SpawnDenial::UnsuitableGround: return "unsuitableGround";
|
||||||
|
case SpawnDenial::NoHeadroom: return "noHeadroom";
|
||||||
|
case SpawnDenial::BlockLightTooHigh: return "blockLightTooHigh";
|
||||||
|
case SpawnDenial::SkyLightTooHigh: return "skyLightTooHigh";
|
||||||
|
case SpawnDenial::LightTooLow: return "lightTooLow";
|
||||||
|
case SpawnDenial::TooCloseToPlayer: return "tooCloseToPlayer";
|
||||||
|
case SpawnDenial::TooFarFromPlayer: return "tooFarFromPlayer";
|
||||||
|
case SpawnDenial::NoStandableCell: return "noStandableCell";
|
||||||
|
case SpawnDenial::NoRuleMatched: return "noRuleMatched";
|
||||||
|
case SpawnDenial::Count: break;
|
||||||
|
}
|
||||||
|
return "unknown";
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SpawnRule::allowsBiome(BiomeKind biome) const {
|
||||||
|
if (biomes.empty()) return true;
|
||||||
|
return std::find(biomes.begin(), biomes.end(), biome) != biomes.end();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SpawnRule::allowsGround(Block block) const {
|
||||||
|
if (groundBlocks.empty()) return isSolid(block);
|
||||||
|
return std::find(groundBlocks.begin(), groundBlocks.end(), block) != groundBlocks.end();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<SpawnRule> defaultSpawnRules() {
|
||||||
|
std::vector<SpawnRule> rules;
|
||||||
|
rules.push_back(makeHostileRule(Species::Zombie, 2, 4));
|
||||||
|
rules.push_back(makeHostileRule(Species::Skeleton, 1, 3));
|
||||||
|
|
||||||
|
SpawnRule creeper = makeHostileRule(Species::Creeper, 1, 2);
|
||||||
|
creeper.biomes = {BiomeKind::Plains, BiomeKind::Forest, BiomeKind::Taiga,
|
||||||
|
BiomeKind::Tundra, BiomeKind::Swamp, BiomeKind::Jungle,
|
||||||
|
BiomeKind::Savanna, BiomeKind::Mountains, BiomeKind::Desert};
|
||||||
|
rules.push_back(creeper);
|
||||||
|
|
||||||
|
rules.push_back(makePassiveRule(
|
||||||
|
Species::Sheep, 2, 4,
|
||||||
|
{BiomeKind::Plains, BiomeKind::Forest, BiomeKind::Savanna, BiomeKind::Taiga}));
|
||||||
|
rules.push_back(makePassiveRule(
|
||||||
|
Species::Cow, 2, 4,
|
||||||
|
{BiomeKind::Plains, BiomeKind::Forest, BiomeKind::Savanna, BiomeKind::Taiga}));
|
||||||
|
rules.push_back(makePassiveRule(
|
||||||
|
Species::Pig, 1, 3, {BiomeKind::Plains, BiomeKind::Forest, BiomeKind::Swamp}));
|
||||||
|
return rules;
|
||||||
|
}
|
||||||
|
|
||||||
|
const SpawnRule* findSpawnRule(const std::vector<SpawnRule>& rules, Species species) {
|
||||||
|
for (const SpawnRule& rule : rules) {
|
||||||
|
if (rule.species == species) return &rule;
|
||||||
|
}
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
Reference in new issue
Block a user