mirror of
https://github.com/cuberite/cuberite.git
synced 2025-01-07 03:16:55 +08:00
Animal spawn fixes
This commit is contained in:
parent
60bcc06f43
commit
b8165aebd4
@ -599,7 +599,10 @@ void cChunk::SpawnMobs(cMobSpawner & a_MobSpawner)
|
||||
ASSERT(TryY > 0);
|
||||
ASSERT(TryY < cChunkDef::Height - 1);
|
||||
|
||||
EMCSBiome Biome = m_ChunkMap->GetBiomeAt(TryX, TryZ);
|
||||
int WorldX, WorldY, WorldZ;
|
||||
PositionToWorldPosition(TryX, TryY, TryZ, WorldX, WorldY, WorldZ);
|
||||
|
||||
EMCSBiome Biome = m_ChunkMap->GetBiomeAt(WorldX, WorldZ);
|
||||
// MG TODO :
|
||||
// Moon cycle (for slime)
|
||||
// check player and playerspawn presence < 24 blocks
|
||||
@ -624,8 +627,6 @@ void cChunk::SpawnMobs(cMobSpawner & a_MobSpawner)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
int WorldX, WorldY, WorldZ;
|
||||
PositionToWorldPosition(TryX, TryY, TryZ, WorldX, WorldY, WorldZ);
|
||||
double ActualX = WorldX + 0.5;
|
||||
double ActualZ = WorldZ + 0.5;
|
||||
newMob->SetPosition(ActualX, WorldY, ActualZ);
|
||||
|
@ -225,8 +225,7 @@ void cComposableGenerator::InitializeGeneratorDefaults(cIniFile & a_IniFile, eDi
|
||||
"BottomLava, "
|
||||
"DeadBushes, "
|
||||
"NaturalPatches, "
|
||||
"PreSimulator, "
|
||||
"Animals"
|
||||
"PreSimulator"
|
||||
);
|
||||
break;
|
||||
} // dimOverworld
|
||||
@ -387,11 +386,7 @@ void cComposableGenerator::InitFinishGens(cIniFile & a_IniFile)
|
||||
}
|
||||
const auto & finisher = split[0];
|
||||
// Finishers, alpha-sorted:
|
||||
if (NoCaseCompare(finisher, "Animals") == 0)
|
||||
{
|
||||
m_FinishGens.push_back(cFinishGenPtr(new cFinishGenPassiveMobs(m_Seed, a_IniFile, m_Dimension)));
|
||||
}
|
||||
else if (NoCaseCompare(finisher, "BottomLava") == 0)
|
||||
if (NoCaseCompare(finisher, "BottomLava") == 0)
|
||||
{
|
||||
int DefaultBottomLavaLevel = (m_Dimension == dimNether) ? 30 : 10;
|
||||
int BottomLavaLevel = a_IniFile.GetValueSetI("Generator", "BottomLavaLevel", DefaultBottomLavaLevel);
|
||||
|
@ -26,8 +26,6 @@
|
||||
#define DEF_OVERWORLD_LAVA_SPRINGS "0, 0; 10, 5; 11, 45; 48, 2; 64, 1; 255, 0"
|
||||
#define DEF_END_WATER_SPRINGS "0, 1; 255, 1"
|
||||
#define DEF_END_LAVA_SPRINGS "0, 1; 255, 1"
|
||||
#define DEF_ANIMAL_SPAWN_PERCENT 10
|
||||
#define DEF_NO_ANIMALS 0
|
||||
|
||||
|
||||
|
||||
@ -1424,169 +1422,6 @@ bool cFinishGenFluidSprings::TryPlaceSpring(cChunkDesc & a_ChunkDesc, int x, int
|
||||
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// cFinishGenPassiveMobs:
|
||||
|
||||
cFinishGenPassiveMobs::cFinishGenPassiveMobs(int a_Seed, cIniFile & a_IniFile, eDimension a_Dimension) :
|
||||
m_Noise(a_Seed)
|
||||
{
|
||||
AString SectionName = "Animals";
|
||||
int DefaultAnimalSpawnChunkPercentage = DEF_ANIMAL_SPAWN_PERCENT;
|
||||
switch (a_Dimension)
|
||||
{
|
||||
case dimOverworld:
|
||||
{
|
||||
DefaultAnimalSpawnChunkPercentage = DEF_ANIMAL_SPAWN_PERCENT;
|
||||
break;
|
||||
}
|
||||
case dimNether:
|
||||
case dimEnd: // No nether or end animals (currently)
|
||||
{
|
||||
DefaultAnimalSpawnChunkPercentage = DEF_NO_ANIMALS;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
ASSERT(!"Unhandled world dimension");
|
||||
DefaultAnimalSpawnChunkPercentage = DEF_NO_ANIMALS;
|
||||
break;
|
||||
}
|
||||
} // switch (dimension)
|
||||
m_AnimalProbability = a_IniFile.GetValueSetI(SectionName, "AnimalSpawnChunkPercentage", DefaultAnimalSpawnChunkPercentage);
|
||||
if ((m_AnimalProbability < 0) || (m_AnimalProbability > 100))
|
||||
{
|
||||
LOGWARNING("[Animals]: AnimalSpawnChunkPercentage is invalid, using the default of \"%d\".", DefaultAnimalSpawnChunkPercentage);
|
||||
m_AnimalProbability = DefaultAnimalSpawnChunkPercentage;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void cFinishGenPassiveMobs::GenFinish(cChunkDesc & a_ChunkDesc)
|
||||
{
|
||||
int chunkX = a_ChunkDesc.GetChunkX();
|
||||
int chunkZ = a_ChunkDesc.GetChunkZ();
|
||||
int ChanceRnd = (m_Noise.IntNoise2DInt(chunkX, chunkZ) / 7) % 100;
|
||||
if (ChanceRnd > m_AnimalProbability)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
eMonsterType RandomMob = GetRandomMob(a_ChunkDesc);
|
||||
if (RandomMob == mtInvalidType)
|
||||
{
|
||||
// No mobs here. Don't send an error, because if the biome was a desert it would return mtInvalidType as well.
|
||||
return;
|
||||
}
|
||||
|
||||
// Try spawning a pack center 10 times, should get roughly the same probability
|
||||
for (int Tries = 0; Tries < 10; Tries++)
|
||||
{
|
||||
int PackCenterX = (m_Noise.IntNoise2DInt(chunkX + chunkZ, Tries) / 7) % cChunkDef::Width;
|
||||
int PackCenterZ = (m_Noise.IntNoise2DInt(chunkX, chunkZ + Tries) / 7) % cChunkDef::Width;
|
||||
if (TrySpawnAnimals(a_ChunkDesc, PackCenterX, a_ChunkDesc.GetHeight(PackCenterX, PackCenterZ), PackCenterZ, RandomMob))
|
||||
{
|
||||
for (int i = 0; i < 3; i++)
|
||||
{
|
||||
int OffsetX = (m_Noise.IntNoise2DInt(chunkX + chunkZ + i, Tries) / 7) % cChunkDef::Width;
|
||||
int OffsetZ = (m_Noise.IntNoise2DInt(chunkX, chunkZ + Tries + i) / 7) % cChunkDef::Width;
|
||||
TrySpawnAnimals(a_ChunkDesc, OffsetX, a_ChunkDesc.GetHeight(OffsetX, OffsetZ), OffsetZ, RandomMob);
|
||||
}
|
||||
return;
|
||||
|
||||
} // if pack center spawn successful
|
||||
} // for tries
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
bool cFinishGenPassiveMobs::TrySpawnAnimals(cChunkDesc & a_ChunkDesc, int a_RelX, int a_RelY, int a_RelZ, eMonsterType AnimalToSpawn)
|
||||
{
|
||||
if ((a_RelY >= cChunkDef::Height - 1) || (a_RelY <= 0))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
BLOCKTYPE BlockAtHead = a_ChunkDesc.GetBlockType(a_RelX, a_RelY + 1, a_RelZ);
|
||||
BLOCKTYPE BlockAtFeet = a_ChunkDesc.GetBlockType(a_RelX, a_RelY, a_RelZ);
|
||||
BLOCKTYPE BlockUnderFeet = a_ChunkDesc.GetBlockType(a_RelX, a_RelY - 1, a_RelZ);
|
||||
|
||||
// Check block below (opaque, grass, water), and above (air)
|
||||
if ((AnimalToSpawn == mtSquid) && (BlockAtFeet != E_BLOCK_WATER))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (
|
||||
(AnimalToSpawn != mtSquid) &&
|
||||
(BlockAtHead != E_BLOCK_AIR) &&
|
||||
(BlockAtFeet != E_BLOCK_AIR) &&
|
||||
(!cBlockInfo::IsTransparent(BlockUnderFeet))
|
||||
)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (
|
||||
(BlockUnderFeet != E_BLOCK_GRASS) &&
|
||||
((AnimalToSpawn == mtWolf) || (AnimalToSpawn == mtRabbit) || (AnimalToSpawn == mtCow) || (AnimalToSpawn == mtSheep) || (AnimalToSpawn == mtChicken) || (AnimalToSpawn == mtPig))
|
||||
)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if ((AnimalToSpawn == mtMooshroom) && (BlockUnderFeet != E_BLOCK_MYCELIUM))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
double AnimalX = static_cast<double>(a_ChunkDesc.GetChunkX() * cChunkDef::Width + a_RelX + 0.5);
|
||||
double AnimalY = a_RelY;
|
||||
double AnimalZ = static_cast<double>(a_ChunkDesc.GetChunkZ() * cChunkDef::Width + a_RelZ + 0.5);
|
||||
|
||||
auto NewMob = cMonster::NewMonsterFromType(AnimalToSpawn);
|
||||
NewMob->SetHealth(NewMob->GetMaxHealth());
|
||||
NewMob->SetPosition(AnimalX, AnimalY, AnimalZ);
|
||||
FLOGD("Spawning {0} #{1} at {2:.02f}", NewMob->GetClass(), NewMob->GetUniqueID(), NewMob->GetPosition());
|
||||
a_ChunkDesc.GetEntities().emplace_back(std::move(NewMob));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
eMonsterType cFinishGenPassiveMobs::GetRandomMob(cChunkDesc & a_ChunkDesc)
|
||||
{
|
||||
std::vector<eMonsterType> ListOfSpawnables;
|
||||
int chunkX = a_ChunkDesc.GetChunkX();
|
||||
int chunkZ = a_ChunkDesc.GetChunkZ();
|
||||
int x = (m_Noise.IntNoise2DInt(chunkX, chunkZ + 10) / 7) % cChunkDef::Width;
|
||||
int z = (m_Noise.IntNoise2DInt(chunkX + chunkZ, chunkZ) / 7) % cChunkDef::Width;
|
||||
|
||||
for (auto MobType : cMobSpawner::GetAllowedMobTypes(a_ChunkDesc.GetBiome(x, z)))
|
||||
{
|
||||
if (cMonster::FamilyFromType(MobType) == cMonster::eFamily::mfPassive)
|
||||
{
|
||||
ListOfSpawnables.push_back(MobType);
|
||||
}
|
||||
}
|
||||
|
||||
if (ListOfSpawnables.empty())
|
||||
{
|
||||
return mtInvalidType;
|
||||
}
|
||||
|
||||
auto RandMob = (static_cast<size_t>(m_Noise.IntNoise2DInt(chunkX - chunkZ + 2, chunkX + 5) / 7) % ListOfSpawnables.size());
|
||||
return ListOfSpawnables[RandMob];
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// cFinishGenOres:
|
||||
|
||||
|
@ -447,39 +447,6 @@ protected:
|
||||
|
||||
|
||||
|
||||
/** This class populates generated chunks with packs of biome-dependant animals
|
||||
Animals: cows, sheep, pigs, mooshrooms, squid, horses, wolves, ocelots */
|
||||
class cFinishGenPassiveMobs :
|
||||
public cFinishGen
|
||||
{
|
||||
public:
|
||||
|
||||
cFinishGenPassiveMobs(int a_Seed, cIniFile & a_IniFile, eDimension a_Dimension);
|
||||
|
||||
protected:
|
||||
|
||||
/** The noise used as the source of randomness */
|
||||
cNoise m_Noise;
|
||||
|
||||
/** Chance, [0..100], that an animal pack will be generated in a chunk */
|
||||
int m_AnimalProbability;
|
||||
|
||||
|
||||
// cFinishGen override:
|
||||
virtual void GenFinish(cChunkDesc & a_ChunkDesc) override;
|
||||
|
||||
/** Returns false if an animal cannot spawn at given coords, else adds it to the chunk's entity list and returns true */
|
||||
bool TrySpawnAnimals(cChunkDesc & a_ChunkDesc, int x, int y, int z, eMonsterType AnimalToSpawn);
|
||||
|
||||
/** Picks a random animal from biome-dependant list for a random position in the chunk.
|
||||
Returns the chosen mob type, or mtInvalid if no mob chosen. */
|
||||
eMonsterType GetRandomMob(cChunkDesc & a_ChunkDesc);
|
||||
} ;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/** Base class for generators that have an ore list attached to them.
|
||||
Provides the storage and parsing for the ore list, as well as the generic plumbing for generating individual ores.
|
||||
Descendants should override GenerateOre() to provide the specific ore generation technique.
|
||||
|
@ -152,8 +152,8 @@ bool cMobSpawner::CanSpawnHere(cChunk * a_Chunk, Vector3i a_RelPos, eMonsterType
|
||||
case mtSheep:
|
||||
{
|
||||
return (
|
||||
(targetBlock == E_BLOCK_AIR) &&
|
||||
(blockAbove == E_BLOCK_AIR) &&
|
||||
(!cBlockInfo::IsTransparent(targetBlock)) &&
|
||||
(!cBlockInfo::IsTransparent(blockAbove)) &&
|
||||
(blockBelow == E_BLOCK_GRASS) &&
|
||||
(skyLight >= 9)
|
||||
);
|
||||
|
Loading…
Reference in New Issue
Block a user