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