mirror of
https://github.com/cuberite/cuberite.git
synced 2025-01-05 10:27:10 +08:00
adding endermite (#5460)
* First Draft of adding endermite * Update src/Mobs/Endermite.h Co-authored-by: x12xx12x <44411062+12xx12@users.noreply.github.com> * Adding Protocols + SpawnEgg TODO: don't forget to put the endermite in core plugin for the summon command * Adding endermite to monster.ini * Adding 5% change of spawning endermite when throwing enderpearl * Spawn endermite at last position instead of Hit Position + .cache to .gitignore * fixup! Spawn endermite at last position instead of Hit Position + .cache to .gitignore * destroy endermite if 2 min, not if name is set * Syntax * Adding Enderman targeting endermite + fixing syntax * Fixing compile error + return error [but crash on enderman spawn] * Fix crash but enderman doesn't target * Enderman targeting endermite finished * checking style because i'm a noob at git... * fixup! checking style because i'm a noob at git... * Added endermite egg meta to docs * Final touches Removed unnecesary imports fixed callback to run only in sight distance and actually check sigtlines * Fixed error after not pulling branch --------- Co-authored-by: x12xx12x <44411062+12xx12@users.noreply.github.com> Co-authored-by: Debucquoy <debucqquoy.anthony@gmail.com>
This commit is contained in:
parent
a819f37fa1
commit
7db4e20fd7
2
.gitignore
vendored
2
.gitignore
vendored
@ -46,6 +46,8 @@ GPUCache
|
||||
*.cbp
|
||||
## KDevelop
|
||||
*.kdev*
|
||||
## Vim
|
||||
.cache/
|
||||
|
||||
# world inside source
|
||||
ChunkWorx.ini
|
||||
|
@ -17849,6 +17849,10 @@ end
|
||||
{
|
||||
Notes = "A mask that indicates the bits of the metadata that specify the facing of redstone repeaters.",
|
||||
},
|
||||
E_META_SPAWN_EGG_ENDERMITE =
|
||||
{
|
||||
Notes = "",
|
||||
},
|
||||
E_META_SPAWN_EGG_WITHER_SKELETON =
|
||||
{
|
||||
Notes = ""
|
||||
|
@ -48,6 +48,13 @@ AttackRate=1.0
|
||||
MaxHealth=200
|
||||
SightDistance=25.0
|
||||
|
||||
[Endermite]
|
||||
AttackDamage=2.0
|
||||
AttackRange=0.75
|
||||
AttackRate=1.0
|
||||
MaxHealth=8
|
||||
SightDistance=16.0
|
||||
|
||||
[Enderman]
|
||||
AttackDamage=4.0
|
||||
AttackRange=1.0
|
||||
|
@ -1130,6 +1130,7 @@ enum ENUM_ITEM_META : short
|
||||
E_META_SPAWN_EGG_WITHER = 64,
|
||||
E_META_SPAWN_EGG_BAT = 65,
|
||||
E_META_SPAWN_EGG_WITCH = 66,
|
||||
E_META_SPAWN_EGG_ENDERMITE = 67,
|
||||
E_META_SPAWN_EGG_GUARDIAN = 68,
|
||||
E_META_SPAWN_EGG_PIG = 90,
|
||||
E_META_SPAWN_EGG_SHEEP = 91,
|
||||
|
@ -494,6 +494,7 @@ bool cEntity::DoTakeDamage(TakeDamageInfo & a_TDI)
|
||||
case mtSpider:
|
||||
case mtCaveSpider:
|
||||
case mtSilverfish:
|
||||
case mtEndermite:
|
||||
{
|
||||
MagicalCriticalHit = true;
|
||||
a_TDI.FinalDamage += 2.5f * BaneOfArthropodsLevel;
|
||||
|
@ -1,6 +1,8 @@
|
||||
|
||||
#include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules
|
||||
|
||||
#include "FastRandom.h"
|
||||
#include "Mobs/MonsterTypes.h"
|
||||
#include "ThrownEnderPearlEntity.h"
|
||||
#include "Player.h"
|
||||
|
||||
@ -56,11 +58,25 @@ void cThrownEnderPearlEntity::TeleportCreator(Vector3d a_HitPos)
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
|
||||
GetWorld()->FindAndDoWithPlayer(m_CreatorData.m_Name, [=](cPlayer & a_Entity)
|
||||
{
|
||||
|
||||
auto & Random = GetRandomProvider();
|
||||
|
||||
// 5% chance to spawn an endermite
|
||||
if (Random.RandBool(0.05))
|
||||
{
|
||||
Vector3d PlayerPosition = a_Entity.GetPosition();
|
||||
m_World->SpawnMob(PlayerPosition.x, PlayerPosition.y, PlayerPosition.z, mtEndermite);
|
||||
}
|
||||
|
||||
|
||||
// Teleport the creator here, make them take 5 damage:
|
||||
a_Entity.TeleportToCoords(a_HitPos.x, a_HitPos.y + 0.2, a_HitPos.z);
|
||||
a_Entity.TakeDamage(dtEnderPearl, this, 5, 0);
|
||||
|
||||
return false;
|
||||
});
|
||||
}
|
||||
|
@ -72,6 +72,7 @@ public:
|
||||
case E_META_SPAWN_EGG_COW: return mtCow;
|
||||
case E_META_SPAWN_EGG_CREEPER: return mtCreeper;
|
||||
case E_META_SPAWN_EGG_ENDERMAN: return mtEnderman;
|
||||
case E_META_SPAWN_EGG_ENDERMITE: return mtEndermite;
|
||||
case E_META_SPAWN_EGG_GHAST: return mtGhast;
|
||||
case E_META_SPAWN_EGG_GUARDIAN: return mtGuardian;
|
||||
case E_META_SPAWN_EGG_HORSE: return mtHorse;
|
||||
|
@ -3,6 +3,9 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "ItemHandler.h"
|
||||
#include "Entities/ProjectileEntity.h"
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -3,9 +3,9 @@
|
||||
|
||||
#include "AggressiveMonster.h"
|
||||
|
||||
#include "../World.h"
|
||||
#include "../Entities/Player.h"
|
||||
#include "../LineBlockTracer.h"
|
||||
#include "LineBlockTracer.h"
|
||||
#include "World.h"
|
||||
#include "Entities/Player.h"
|
||||
|
||||
|
||||
|
||||
@ -46,6 +46,61 @@ void cAggressiveMonster::EventSeePlayer(cPlayer * a_Player, cChunk & a_Chunk)
|
||||
|
||||
|
||||
|
||||
cMonster * cAggressiveMonster::GetMonsterOfTypeInSight(eMonsterType a_MobType, unsigned int a_SightDistance)
|
||||
{
|
||||
|
||||
cMonster * FoundTarget = nullptr;
|
||||
auto MinimumDistance = static_cast<double>(a_SightDistance * a_SightDistance);
|
||||
|
||||
class cCallback : public cBlockTracer::cCallbacks
|
||||
{
|
||||
public:
|
||||
bool OnNextBlock(Vector3i a_BlockPos, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, eBlockFace a_EntryFace) override
|
||||
{
|
||||
return a_BlockType != E_BLOCK_AIR;
|
||||
}
|
||||
};
|
||||
|
||||
auto Callbacks = cCallback();
|
||||
auto Tracer = cLineBlockTracer(*GetWorld(), Callbacks);
|
||||
|
||||
cEntityCallback Callback = [&](cEntity & a_Entity)
|
||||
{
|
||||
if (!a_Entity.IsMob())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
auto & Other = dynamic_cast<cMonster &>(a_Entity);
|
||||
if (Other.GetMobType() != a_MobType)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
Vector3d MyHeadPosition = GetPosition().addedY(GetHeight());
|
||||
Vector3d TargetPosition = Other.GetPosition().addedY(Other.GetHeight());
|
||||
double TargetDistance = (MyHeadPosition - TargetPosition).SqrLength();
|
||||
|
||||
if (
|
||||
(MinimumDistance > TargetDistance) &&
|
||||
(TargetDistance < (a_SightDistance * a_SightDistance))
|
||||
)
|
||||
{
|
||||
FoundTarget = & Other;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
cBoundingBox CheckZone(GetPosition().addedXZ(-a_SightDistance, -a_SightDistance), GetPosition().addedXZ(a_SightDistance, a_SightDistance));
|
||||
m_World->ForEachEntityInBox(CheckZone, Callback);
|
||||
return FoundTarget;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void cAggressiveMonster::Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk)
|
||||
{
|
||||
Super::Tick(a_Dt, a_Chunk);
|
||||
|
@ -30,12 +30,18 @@ public:
|
||||
|
||||
virtual void EventSeePlayer(cPlayer * a_Player, cChunk & a_Chunk) override;
|
||||
|
||||
/**
|
||||
* Check if a monster of certain type is in sight
|
||||
*
|
||||
* @param a_mobtype the mob type to find
|
||||
* @param SightDistance max distance to check
|
||||
*
|
||||
* @return pointer to the mob found
|
||||
*/
|
||||
cMonster * GetMonsterOfTypeInSight(eMonsterType a_mobtype, unsigned int SightDistance=16);
|
||||
|
||||
/** Try to perform attack
|
||||
returns true if attack was deemed successful (hit player, fired projectile, creeper exploded, etc.) even if it didn't actually do damage
|
||||
return false if e.g. the mob is still in cooldown from a previous attack */
|
||||
virtual bool Attack(std::chrono::milliseconds a_Dt);
|
||||
} ;
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -9,6 +9,7 @@ target_sources(
|
||||
Cow.cpp
|
||||
Creeper.cpp
|
||||
EnderDragon.cpp
|
||||
Endermite.cpp
|
||||
Enderman.cpp
|
||||
Ghast.cpp
|
||||
Giant.cpp
|
||||
@ -49,6 +50,7 @@ target_sources(
|
||||
Cow.h
|
||||
Creeper.h
|
||||
EnderDragon.h
|
||||
Endermite.h
|
||||
Enderman.h
|
||||
Ghast.h
|
||||
Giant.h
|
||||
|
@ -149,6 +149,29 @@ void cEnderman::Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk)
|
||||
return;
|
||||
}
|
||||
|
||||
if (m_EMState != CHASING)
|
||||
{
|
||||
cMonster * EndermiteFound = GetMonsterOfTypeInSight(mtEndermite, 64);
|
||||
if (EndermiteFound != nullptr)
|
||||
{
|
||||
SetTarget(EndermiteFound);
|
||||
m_EMState = CHASING;
|
||||
m_bIsScreaming = true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
const auto Target = GetTarget();
|
||||
if (Target != nullptr)
|
||||
{
|
||||
if (!Target->IsTicking())
|
||||
{
|
||||
m_EMState = IDLE;
|
||||
m_bIsScreaming = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
PREPARE_REL_AND_CHUNK(GetPosition().Floor(), a_Chunk);
|
||||
if (!RelSuccess)
|
||||
{
|
||||
|
41
src/Mobs/Endermite.cpp
Normal file
41
src/Mobs/Endermite.cpp
Normal file
@ -0,0 +1,41 @@
|
||||
|
||||
#include "Globals.h"
|
||||
|
||||
#include "Endermite.h"
|
||||
|
||||
#include "../World.h"
|
||||
#include "../Chunk.h"
|
||||
#include "../Blocks/BlockHandler.h"
|
||||
#include "../Blocks/BlockInfested.h"
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
cEndermite::cEndermite() :
|
||||
Super("Endermite", mtEndermite, "entity.endermite.hurt", "entity.endermite.death", "entity.endermite.ambient", 0.4f, 0.3f),
|
||||
m_Timer(0),
|
||||
m_Lifetime(2 * 1000 * 60) // 2 minutes (2 * 1000 (mili to sec) * 60 (sec to min) * 2 because tick = 0.5 sec)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void cEndermite::Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk)
|
||||
{
|
||||
Super::Tick(a_Dt, a_Chunk);
|
||||
|
||||
// Not destroying the endermite if a name is set
|
||||
if (m_CustomName.empty())
|
||||
{
|
||||
m_Timer += a_Dt;
|
||||
// Destroy the endermite after 2 minutes
|
||||
if (m_Timer > m_Lifetime)
|
||||
{
|
||||
Destroy();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
24
src/Mobs/Endermite.h
Normal file
24
src/Mobs/Endermite.h
Normal file
@ -0,0 +1,24 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "AggressiveMonster.h"
|
||||
|
||||
|
||||
|
||||
class cEndermite:
|
||||
public cAggressiveMonster
|
||||
{
|
||||
using Super = cAggressiveMonster;
|
||||
|
||||
// Endermite should despawn in two minutes
|
||||
std::chrono::milliseconds m_Timer;
|
||||
std::chrono::milliseconds m_Lifetime;
|
||||
|
||||
public:
|
||||
|
||||
cEndermite();
|
||||
|
||||
CLASS_PROTODEF(cEndermite)
|
||||
|
||||
void Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk) override;
|
||||
} ;
|
@ -5,6 +5,7 @@
|
||||
#include "Cow.h"
|
||||
#include "Creeper.h"
|
||||
#include "Enderman.h"
|
||||
#include "Endermite.h"
|
||||
#include "EnderDragon.h"
|
||||
#include "Ghast.h"
|
||||
#include "Giant.h"
|
||||
|
@ -45,6 +45,7 @@ static const struct
|
||||
{mtCow, "cow", "Cow", "cow"},
|
||||
{mtCreeper, "creeper", "Creeper", "creeper"},
|
||||
{mtEnderman, "enderman", "Enderman", "enderman"},
|
||||
{mtEndermite, "endermite", "Endermite", "endermite"},
|
||||
{mtEnderDragon, "enderdragon", "EnderDragon", "ender_dragon"},
|
||||
{mtGhast, "ghast", "Ghast", "ghast"},
|
||||
{mtGiant, "giant", "Giant", "giant"},
|
||||
@ -653,6 +654,11 @@ void cMonster::KilledBy(TakeDamageInfo & a_TDI)
|
||||
Reward = GetRandomProvider().RandInt(6, 8);
|
||||
break;
|
||||
}
|
||||
case mtEndermite:
|
||||
{
|
||||
Reward = 3;
|
||||
break;
|
||||
}
|
||||
case mtBlaze:
|
||||
{
|
||||
Reward = 10;
|
||||
@ -1286,6 +1292,7 @@ std::unique_ptr<cMonster> cMonster::NewMonsterFromType(eMonsterType a_MobType)
|
||||
case mtCow: return std::make_unique<cCow>();
|
||||
case mtCreeper: return std::make_unique<cCreeper>();
|
||||
case mtEnderDragon: return std::make_unique<cEnderDragon>();
|
||||
case mtEndermite: return std::make_unique<cEndermite>();
|
||||
case mtEnderman: return std::make_unique<cEnderman>();
|
||||
case mtGhast: return std::make_unique<cGhast>();
|
||||
case mtGiant: return std::make_unique<cGiant>();
|
||||
|
@ -937,8 +937,6 @@ void cProtocol_1_10_0::WriteMobMetadata(cPacketizer & a_Pkt, const cMonster & a_
|
||||
}
|
||||
case mtCat:
|
||||
|
||||
case mtEndermite:
|
||||
|
||||
case mtPolarBear:
|
||||
|
||||
case mtShulker:
|
||||
@ -955,6 +953,7 @@ void cProtocol_1_10_0::WriteMobMetadata(cPacketizer & a_Pkt, const cMonster & a_
|
||||
|
||||
case mtCaveSpider:
|
||||
case mtEnderDragon:
|
||||
case mtEndermite:
|
||||
case mtGiant:
|
||||
case mtIronGolem:
|
||||
case mtMooshroom:
|
||||
|
@ -1230,8 +1230,6 @@ void cProtocol_1_11_0::WriteMobMetadata(cPacketizer & a_Pkt, const cMonster & a_
|
||||
case mtDonkey:
|
||||
case mtMule:
|
||||
|
||||
case mtEndermite:
|
||||
|
||||
case mtEvoker:
|
||||
|
||||
case mtLlama:
|
||||
@ -1254,6 +1252,7 @@ void cProtocol_1_11_0::WriteMobMetadata(cPacketizer & a_Pkt, const cMonster & a_
|
||||
|
||||
case mtCaveSpider:
|
||||
case mtEnderDragon:
|
||||
case mtEndermite:
|
||||
case mtGiant:
|
||||
case mtIronGolem:
|
||||
case mtMooshroom:
|
||||
|
@ -935,8 +935,6 @@ void cProtocol_1_12::WriteMobMetadata(cPacketizer & a_Pkt, const cMonster & a_Mo
|
||||
case mtDonkey:
|
||||
case mtMule:
|
||||
|
||||
case mtEndermite:
|
||||
|
||||
case mtEvoker:
|
||||
|
||||
case mtHusk:
|
||||
@ -965,6 +963,7 @@ void cProtocol_1_12::WriteMobMetadata(cPacketizer & a_Pkt, const cMonster & a_Mo
|
||||
break;
|
||||
}
|
||||
|
||||
case mtEndermite:
|
||||
case mtGiant:
|
||||
case mtSilverfish:
|
||||
case mtSquid:
|
||||
|
@ -1299,8 +1299,6 @@ void cProtocol_1_13::WriteMobMetadata(cPacketizer & a_Pkt, const cMonster & a_Mo
|
||||
|
||||
case mtDrowned:
|
||||
|
||||
case mtEndermite:
|
||||
|
||||
case mtEvoker:
|
||||
|
||||
case mtIllusioner:
|
||||
@ -1348,6 +1346,7 @@ void cProtocol_1_13::WriteMobMetadata(cPacketizer & a_Pkt, const cMonster & a_Mo
|
||||
break;
|
||||
}
|
||||
|
||||
case mtEndermite:
|
||||
case mtGiant:
|
||||
case mtSilverfish:
|
||||
case mtSquid:
|
||||
|
@ -1602,8 +1602,6 @@ void cProtocol_1_14::WriteMobMetadata(cPacketizer & a_Pkt, const cMonster & a_Mo
|
||||
|
||||
case mtDrowned:
|
||||
|
||||
case mtEndermite:
|
||||
|
||||
case mtEvoker:
|
||||
|
||||
case mtIllusioner:
|
||||
@ -1651,6 +1649,7 @@ void cProtocol_1_14::WriteMobMetadata(cPacketizer & a_Pkt, const cMonster & a_Mo
|
||||
break;
|
||||
}
|
||||
|
||||
case mtEndermite:
|
||||
case mtGiant:
|
||||
case mtSilverfish:
|
||||
case mtSquid:
|
||||
|
@ -3761,7 +3761,6 @@ void cProtocol_1_8_0::WriteMobMetadata(cPacketizer & a_Pkt, const cMonster & a_M
|
||||
|
||||
case mtCat:
|
||||
|
||||
case mtEndermite:
|
||||
|
||||
case mtDonkey:
|
||||
case mtMule:
|
||||
@ -3779,6 +3778,7 @@ void cProtocol_1_8_0::WriteMobMetadata(cPacketizer & a_Pkt, const cMonster & a_M
|
||||
case mtIronGolem:
|
||||
case mtMooshroom:
|
||||
case mtSilverfish:
|
||||
case mtEndermite:
|
||||
case mtSnowGolem:
|
||||
case mtSpider:
|
||||
case mtSquid:
|
||||
|
@ -2318,8 +2318,6 @@ void cProtocol_1_9_0::WriteMobMetadata(cPacketizer & a_Pkt, const cMonster & a_M
|
||||
|
||||
case mtDonkey:
|
||||
|
||||
case mtEndermite:
|
||||
|
||||
case mtMule:
|
||||
|
||||
case mtStray:
|
||||
@ -2336,6 +2334,7 @@ void cProtocol_1_9_0::WriteMobMetadata(cPacketizer & a_Pkt, const cMonster & a_M
|
||||
|
||||
case mtCaveSpider:
|
||||
case mtEnderDragon:
|
||||
case mtEndermite:
|
||||
case mtGiant:
|
||||
case mtIronGolem:
|
||||
case mtMooshroom:
|
||||
|
Loading…
Reference in New Issue
Block a user