Adding more customize options to mob spawners and improving the way to look for surrounding entities (#4955)
* added nearly any customize option * fixed unnecessary diff added comments * removed unnecessary const qualifier * fixed build * changed to ForEachEntityInBox * added docs * updated lua api description * checkstyle * added changes suggested by @peterbell10 And now the player may break the server by setting ridiculous ranges * updated docs changed cast to static cast * fixed clang * fixed clang on WSSAnvil.cpp Co-authored-by: 12xx12 <12xx12100@gmail.com>
This commit is contained in:
@@ -33,6 +33,12 @@ void cMobSpawnerEntity::CopyFrom(const cBlockEntity & a_Src)
|
||||
m_Entity = src.m_Entity;
|
||||
m_IsActive = src.m_IsActive;
|
||||
m_SpawnDelay = src.m_SpawnDelay;
|
||||
m_SpawnCount = src.m_SpawnCount;
|
||||
m_SpawnRange = src.m_SpawnRange;
|
||||
m_MinSpawnDelay = src.m_MinSpawnDelay;
|
||||
m_MaxSpawnDelay = src.m_MaxSpawnDelay;
|
||||
m_MaxNearbyEntities = src.m_MaxNearbyEntities;
|
||||
m_RequiredPlayerRange = src.m_RequiredPlayerRange;
|
||||
}
|
||||
|
||||
|
||||
@@ -114,7 +120,7 @@ bool cMobSpawnerEntity::Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk)
|
||||
|
||||
void cMobSpawnerEntity::ResetTimer(void)
|
||||
{
|
||||
m_SpawnDelay = GetRandomProvider().RandInt<short>(200, 800);
|
||||
m_SpawnDelay = GetRandomProvider().RandInt<short>(m_MinSpawnDelay, m_MaxSpawnDelay);
|
||||
m_World->BroadcastBlockEntity(GetPos());
|
||||
}
|
||||
|
||||
@@ -125,7 +131,7 @@ void cMobSpawnerEntity::ResetTimer(void)
|
||||
void cMobSpawnerEntity::SpawnEntity(void)
|
||||
{
|
||||
auto NearbyEntities = GetNearbyMonsterNum(m_Entity);
|
||||
if (NearbyEntities >= 6)
|
||||
if (NearbyEntities >= m_MaxNearbyEntities)
|
||||
{
|
||||
ResetTimer();
|
||||
return;
|
||||
@@ -136,18 +142,18 @@ void cMobSpawnerEntity::SpawnEntity(void)
|
||||
auto & Random = GetRandomProvider();
|
||||
|
||||
bool HaveSpawnedEntity = false;
|
||||
for (size_t i = 0; i < 4; i++)
|
||||
for (short I = 0; I < m_SpawnCount; I++)
|
||||
{
|
||||
if (NearbyEntities >= 6)
|
||||
if (NearbyEntities >= m_MaxNearbyEntities)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
auto SpawnRelPos(GetRelPos());
|
||||
SpawnRelPos += Vector3i(
|
||||
static_cast<int>((Random.RandReal<double>() - Random.RandReal<double>()) * 4.0),
|
||||
static_cast<int>((Random.RandReal<double>() - Random.RandReal<double>()) * static_cast<double>(m_SpawnRange)),
|
||||
Random.RandInt(-1, 1),
|
||||
static_cast<int>((Random.RandReal<double>() - Random.RandReal<double>()) * 4.0)
|
||||
static_cast<int>((Random.RandReal<double>() - Random.RandReal<double>()) * static_cast<double>(m_SpawnRange))
|
||||
);
|
||||
|
||||
auto Chunk = a_Chunk.GetRelNeighborChunkAdjustCoords(SpawnRelPos);
|
||||
@@ -191,39 +197,24 @@ void cMobSpawnerEntity::SpawnEntity(void)
|
||||
|
||||
int cMobSpawnerEntity::GetNearbyPlayersNum(void)
|
||||
{
|
||||
auto SpawnerPos = Vector3d(0.5, 0.5, 0.5) + m_Pos;
|
||||
int NumPlayers = 0;
|
||||
|
||||
class cCallback : public cChunkDataCallback
|
||||
auto Callback = [&] (cEntity & a_Entity)
|
||||
{
|
||||
public:
|
||||
cCallback(Vector3d a_SpawnerPos, int & a_NumPlayers) :
|
||||
m_SpawnerPos(a_SpawnerPos),
|
||||
m_NumPlayers(a_NumPlayers)
|
||||
if (!a_Entity.IsPlayer())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
virtual void Entity(cEntity * a_Entity) override
|
||||
if ((m_Pos - a_Entity.GetPosition()).Length() <= m_RequiredPlayerRange)
|
||||
{
|
||||
if (!a_Entity->IsPlayer())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if ((m_SpawnerPos - a_Entity->GetPosition()).Length() <= 16)
|
||||
{
|
||||
m_NumPlayers++;
|
||||
}
|
||||
NumPlayers++;
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
protected:
|
||||
Vector3d m_SpawnerPos;
|
||||
int & m_NumPlayers;
|
||||
} Callback(SpawnerPos, NumPlayers);
|
||||
auto PlayerBoundingBox = cBoundingBox(Vector3d(m_Pos.x, m_Pos.y - m_RequiredPlayerRange, m_Pos.z), m_RequiredPlayerRange, m_RequiredPlayerRange * 2);
|
||||
|
||||
int ChunkX = GetChunkX();
|
||||
int ChunkZ = GetChunkZ();
|
||||
m_World->ForEachChunkInRect(ChunkX - 1, ChunkX + 1, ChunkZ - 1, ChunkZ + 1, Callback);
|
||||
m_World->ForEachEntityInBox(PlayerBoundingBox, Callback);
|
||||
|
||||
return NumPlayers;
|
||||
}
|
||||
@@ -234,47 +225,26 @@ int cMobSpawnerEntity::GetNearbyPlayersNum(void)
|
||||
|
||||
int cMobSpawnerEntity::GetNearbyMonsterNum(eMonsterType a_EntityType)
|
||||
{
|
||||
auto SpawnerPos = Vector3d(0.5, 0.5, 0.5) + m_Pos;
|
||||
int NumEntities = 0;
|
||||
|
||||
class cCallback : public cChunkDataCallback
|
||||
auto Callback = [&] (cEntity & a_Entity)
|
||||
{
|
||||
public:
|
||||
cCallback(Vector3d a_SpawnerPos, eMonsterType a_CallbackEntityType, int & a_NumEntities) :
|
||||
m_SpawnerPos(a_SpawnerPos),
|
||||
m_EntityType(a_CallbackEntityType),
|
||||
m_NumEntities(a_NumEntities)
|
||||
if (!a_Entity.IsMob())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
virtual void Entity(cEntity * a_Entity) override
|
||||
auto & Mob = static_cast<cMonster &>(a_Entity);
|
||||
if (Mob.GetMobType() == m_Entity)
|
||||
{
|
||||
if (!a_Entity->IsMob())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
cMonster * Mob = static_cast<cMonster *>(a_Entity);
|
||||
if (Mob->GetMobType() != m_EntityType)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if ((Diff(m_SpawnerPos.x, a_Entity->GetPosX()) <= 8.0) && (Diff(m_SpawnerPos.y, a_Entity->GetPosY()) <= 4.0) && (Diff(m_SpawnerPos.z, a_Entity->GetPosZ()) <= 8.0))
|
||||
{
|
||||
m_NumEntities++;
|
||||
}
|
||||
NumEntities++;
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
protected:
|
||||
Vector3d m_SpawnerPos;
|
||||
eMonsterType m_EntityType;
|
||||
int & m_NumEntities;
|
||||
} Callback(SpawnerPos, a_EntityType, NumEntities);
|
||||
auto EntityBoundingBox = cBoundingBox(Vector3d(m_Pos.x, m_Pos.y - 4, m_Pos.z), m_SpawnRange, 8);
|
||||
|
||||
int ChunkX = GetChunkX();
|
||||
int ChunkZ = GetChunkZ();
|
||||
m_World->ForEachChunkInRect(ChunkX - 1, ChunkX + 1, ChunkZ - 1, ChunkZ + 1, Callback);
|
||||
m_World->ForEachEntityInBox(EntityBoundingBox, Callback);
|
||||
|
||||
return NumEntities;
|
||||
}
|
||||
|
||||
@@ -33,46 +33,68 @@ public: // tolua_export
|
||||
virtual bool UsedBy(cPlayer * a_Player) override;
|
||||
virtual bool Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk) override;
|
||||
|
||||
static const char * GetClassStatic(void) { return "cMobSpawnerEntity"; }
|
||||
// tolua_begin
|
||||
|
||||
/** Upate the active flag from the mob spawner. This function will called every 5 seconds from the Tick() function. */
|
||||
/** Update the active flag from the mob spawner. This function will called every 5 seconds from the Tick() function. */
|
||||
void UpdateActiveState(void);
|
||||
|
||||
/** Sets the spawn delay to a new random value. */
|
||||
void ResetTimer(void);
|
||||
|
||||
/** Spawns the entity. This function automaticly change the spawn delay! */
|
||||
/** Spawns the entity. This function automatically change the spawn delay! */
|
||||
void SpawnEntity(void);
|
||||
|
||||
/** Returns the entity type that will be spawn by this mob spawner. */
|
||||
eMonsterType GetEntity(void) const { return m_Entity; }
|
||||
|
||||
/** Sets the entity type who will be spawn by this mob spawner. */
|
||||
void SetEntity(eMonsterType a_EntityType) { m_Entity = a_EntityType; }
|
||||
|
||||
/** Returns the spawn delay. This is the tick delay that is needed to spawn new monsters. */
|
||||
short GetSpawnDelay(void) const { return m_SpawnDelay; }
|
||||
|
||||
/** Sets the spawn delay. */
|
||||
void SetSpawnDelay(short a_Delay) { m_SpawnDelay = a_Delay; }
|
||||
|
||||
/** Returns the amount of the nearby players in a 16-block radius. */
|
||||
// Getters
|
||||
int GetNearbyMonsterNum(eMonsterType a_EntityType);
|
||||
int GetNearbyPlayersNum(void);
|
||||
|
||||
/** Returns the amount of this monster type in a 8-block radius (Y: 4-block radius). */
|
||||
int GetNearbyMonsterNum(eMonsterType a_EntityType);
|
||||
eMonsterType GetEntity(void) const { return m_Entity; }
|
||||
short GetSpawnCount(void) const { return m_SpawnCount; }
|
||||
short GetSpawnRange(void) const { return m_SpawnRange; }
|
||||
short GetSpawnDelay(void) const { return m_SpawnDelay; }
|
||||
short GetMinSpawnDelay(void) const { return m_MinSpawnDelay; }
|
||||
short GetMaxSpawnDelay(void) const { return m_MaxSpawnDelay; }
|
||||
short GetMaxNearbyEntities(void) const { return m_MaxNearbyEntities; }
|
||||
short GetRequiredPlayerRange(void) const { return m_RequiredPlayerRange; }
|
||||
|
||||
// Setters
|
||||
void SetEntity(eMonsterType a_EntityType) { m_Entity = a_EntityType; }
|
||||
void SetSpawnDelay(short a_Delay) { m_SpawnDelay = a_Delay; }
|
||||
void SetSpawnCount(short a_SpawnCount) { m_SpawnCount = a_SpawnCount; }
|
||||
void SetSpawnRange(short a_SpawnRange) { m_SpawnRange = a_SpawnRange; }
|
||||
void SetMinSpawnDelay(short a_Min) { m_MinSpawnDelay = a_Min; }
|
||||
void SetMaxSpawnDelay(short a_Max) { m_MaxSpawnDelay = a_Max; }
|
||||
void SetMaxNearbyEntities(short a_MaxNearbyEntities) { m_MaxNearbyEntities = a_MaxNearbyEntities; }
|
||||
void SetRequiredPlayerRange(short a_RequiredPlayerRange) { m_RequiredPlayerRange = a_RequiredPlayerRange; }
|
||||
|
||||
// tolua_end
|
||||
|
||||
static const char * GetClassStatic(void) { return "cMobSpawnerEntity"; }
|
||||
|
||||
private:
|
||||
/** The entity to spawn. */
|
||||
eMonsterType m_Entity;
|
||||
|
||||
/** Time in ticks until the next entity spawns */
|
||||
short m_SpawnDelay;
|
||||
|
||||
bool m_IsActive;
|
||||
|
||||
/** Number of entities the spawner tries to spawn each activation. */
|
||||
short m_SpawnCount = 4;
|
||||
|
||||
/** Diameter of the square the new monsters are spawned in */
|
||||
short m_SpawnRange = 8;
|
||||
|
||||
short m_MinSpawnDelay = 200;
|
||||
|
||||
short m_MaxSpawnDelay = 800;
|
||||
|
||||
/** Maximum amount of the same entity type in proximity. */
|
||||
short m_MaxNearbyEntities = 6;
|
||||
|
||||
/** Maximum distance to player for activation */
|
||||
short m_RequiredPlayerRange = 16;
|
||||
|
||||
} ; // tolua_end
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user