mirror of
https://github.com/cuberite/cuberite.git
synced 2025-01-09 04:19:26 +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 > 0);
|
||||||
ASSERT(TryY < cChunkDef::Height - 1);
|
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 :
|
// MG TODO :
|
||||||
// Moon cycle (for slime)
|
// Moon cycle (for slime)
|
||||||
// check player and playerspawn presence < 24 blocks
|
// check player and playerspawn presence < 24 blocks
|
||||||
@ -624,8 +627,6 @@ void cChunk::SpawnMobs(cMobSpawner & a_MobSpawner)
|
|||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
int WorldX, WorldY, WorldZ;
|
|
||||||
PositionToWorldPosition(TryX, TryY, TryZ, WorldX, WorldY, WorldZ);
|
|
||||||
double ActualX = WorldX + 0.5;
|
double ActualX = WorldX + 0.5;
|
||||||
double ActualZ = WorldZ + 0.5;
|
double ActualZ = WorldZ + 0.5;
|
||||||
newMob->SetPosition(ActualX, WorldY, ActualZ);
|
newMob->SetPosition(ActualX, WorldY, ActualZ);
|
||||||
|
@ -225,8 +225,7 @@ void cComposableGenerator::InitializeGeneratorDefaults(cIniFile & a_IniFile, eDi
|
|||||||
"BottomLava, "
|
"BottomLava, "
|
||||||
"DeadBushes, "
|
"DeadBushes, "
|
||||||
"NaturalPatches, "
|
"NaturalPatches, "
|
||||||
"PreSimulator, "
|
"PreSimulator"
|
||||||
"Animals"
|
|
||||||
);
|
);
|
||||||
break;
|
break;
|
||||||
} // dimOverworld
|
} // dimOverworld
|
||||||
@ -387,11 +386,7 @@ void cComposableGenerator::InitFinishGens(cIniFile & a_IniFile)
|
|||||||
}
|
}
|
||||||
const auto & finisher = split[0];
|
const auto & finisher = split[0];
|
||||||
// Finishers, alpha-sorted:
|
// Finishers, alpha-sorted:
|
||||||
if (NoCaseCompare(finisher, "Animals") == 0)
|
if (NoCaseCompare(finisher, "BottomLava") == 0)
|
||||||
{
|
|
||||||
m_FinishGens.push_back(cFinishGenPtr(new cFinishGenPassiveMobs(m_Seed, a_IniFile, m_Dimension)));
|
|
||||||
}
|
|
||||||
else if (NoCaseCompare(finisher, "BottomLava") == 0)
|
|
||||||
{
|
{
|
||||||
int DefaultBottomLavaLevel = (m_Dimension == dimNether) ? 30 : 10;
|
int DefaultBottomLavaLevel = (m_Dimension == dimNether) ? 30 : 10;
|
||||||
int BottomLavaLevel = a_IniFile.GetValueSetI("Generator", "BottomLavaLevel", DefaultBottomLavaLevel);
|
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_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_WATER_SPRINGS "0, 1; 255, 1"
|
||||||
#define DEF_END_LAVA_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:
|
// 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.
|
/** 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.
|
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.
|
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:
|
case mtSheep:
|
||||||
{
|
{
|
||||||
return (
|
return (
|
||||||
(targetBlock == E_BLOCK_AIR) &&
|
(!cBlockInfo::IsTransparent(targetBlock)) &&
|
||||||
(blockAbove == E_BLOCK_AIR) &&
|
(!cBlockInfo::IsTransparent(blockAbove)) &&
|
||||||
(blockBelow == E_BLOCK_GRASS) &&
|
(blockBelow == E_BLOCK_GRASS) &&
|
||||||
(skyLight >= 9)
|
(skyLight >= 9)
|
||||||
);
|
);
|
||||||
|
Loading…
Reference in New Issue
Block a user