summaryrefslogtreecommitdiffstats
path: root/src/Entities/ProjectileEntity.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/Entities/ProjectileEntity.cpp')
-rw-r--r--src/Entities/ProjectileEntity.cpp158
1 files changed, 99 insertions, 59 deletions
diff --git a/src/Entities/ProjectileEntity.cpp b/src/Entities/ProjectileEntity.cpp
index 12ce9a303..e86bb48bd 100644
--- a/src/Entities/ProjectileEntity.cpp
+++ b/src/Entities/ProjectileEntity.cpp
@@ -4,6 +4,7 @@
// Implements the cProjectileEntity class representing the common base class for projectiles, as well as individual projectile types
#include "Globals.h"
+#include "../Bindings/PluginManager.h"
#include "ProjectileEntity.h"
#include "../ClientHandle.h"
#include "Player.h"
@@ -50,12 +51,12 @@ protected:
LOGD("Hit block %d:%d at {%d, %d, %d} face %d, %s (%s)",
a_BlockType, a_BlockMeta,
a_BlockX, a_BlockY, a_BlockZ, a_EntryFace,
- g_BlockIsSolid[a_BlockType] ? "solid" : "non-solid",
+ cBlockInfo::IsSolid(a_BlockType) ? "solid" : "non-solid",
ItemToString(cItem(a_BlockType, 1, a_BlockMeta)).c_str()
);
*/
- if (g_BlockIsSolid[a_BlockType])
+ if (cBlockInfo::IsSolid(a_BlockType))
{
// The projectile hit a solid block
// Calculate the exact hit coords:
@@ -63,9 +64,14 @@ protected:
Vector3d Line1 = m_Projectile->GetPosition();
Vector3d Line2 = Line1 + m_Projectile->GetSpeed();
double LineCoeff = 0;
- char Face;
+ eBlockFace Face;
if (bb.CalcLineIntersection(Line1, Line2, LineCoeff, Face))
{
+ if (cPluginManager::Get()->CallHookProjectileHitBlock(*m_Projectile))
+ {
+ return false;
+ }
+
Vector3d Intersection = Line1 + m_Projectile->GetSpeed() * LineCoeff;
m_Projectile->OnHitSolidBlock(Intersection, Face);
return true;
@@ -138,7 +144,7 @@ public:
// Instead of colliding the bounding box with another bounding box in motion, we collide an enlarged bounding box with a hairline.
// The results should be good enough for our purposes
double LineCoeff;
- char Face;
+ eBlockFace Face;
EntBox.Expand(m_Projectile->GetWidth() / 2, m_Projectile->GetHeight() / 2, m_Projectile->GetWidth() / 2);
if (!EntBox.CalcLineIntersection(m_Pos, m_NextPos, LineCoeff, Face))
{
@@ -147,7 +153,11 @@ public:
}
// TODO: Some entities don't interact with the projectiles (pickups, falling blocks)
- // TODO: Allow plugins to interfere about which entities can be hit
+ if (cPluginManager::Get()->CallHookProjectileHitEntity(*m_Projectile, *a_Entity))
+ {
+ // A plugin disagreed.
+ return false;
+ }
if (LineCoeff < m_MinCoeff)
{
@@ -214,7 +224,7 @@ cProjectileEntity::cProjectileEntity(eKind a_Kind, cEntity * a_Creator, const Ve
-cProjectileEntity * cProjectileEntity::Create(eKind a_Kind, cEntity * a_Creator, double a_X, double a_Y, double a_Z, const Vector3d * a_Speed)
+cProjectileEntity * cProjectileEntity::Create(eKind a_Kind, cEntity * a_Creator, double a_X, double a_Y, double a_Z, const cItem & a_Item, const Vector3d * a_Speed)
{
Vector3d Speed;
if (a_Speed != NULL)
@@ -231,8 +241,15 @@ cProjectileEntity * cProjectileEntity::Create(eKind a_Kind, cEntity * a_Creator,
case pkGhastFireball: return new cGhastFireballEntity (a_Creator, a_X, a_Y, a_Z, Speed);
case pkFireCharge: return new cFireChargeEntity (a_Creator, a_X, a_Y, a_Z, Speed);
case pkExpBottle: return new cExpBottleEntity (a_Creator, a_X, a_Y, a_Z, Speed);
- case pkFirework: return new cFireworkEntity (a_Creator, a_X, a_Y, a_Z );
- // TODO: the rest
+ case pkFirework:
+ {
+ if (a_Item.m_FireworkItem.m_Colours.empty())
+ {
+ return NULL;
+ }
+
+ return new cFireworkEntity(a_Creator, a_X, a_Y, a_Z, a_Item);
+ }
}
LOGWARNING("%s: Unknown projectile kind: %d", __FUNCTION__, a_Kind);
@@ -243,7 +260,7 @@ cProjectileEntity * cProjectileEntity::Create(eKind a_Kind, cEntity * a_Creator,
-void cProjectileEntity::OnHitSolidBlock(const Vector3d & a_HitPos, char a_HitFace)
+void cProjectileEntity::OnHitSolidBlock(const Vector3d & a_HitPos, eBlockFace a_HitFace)
{
// Set the position based on what face was hit:
SetPosition(a_HitPos);
@@ -276,6 +293,7 @@ AString cProjectileEntity::GetMCAClassName(void) const
case pkExpBottle: return "ThrownExpBottle";
case pkSplashPotion: return "ThrownPotion";
case pkWitherSkull: return "WitherSkull";
+ case pkFirework: return "Firework";
case pkFishingFloat: return ""; // Unknown, perhaps MC doesn't save this?
}
ASSERT(!"Unhandled projectile entity kind!");
@@ -353,13 +371,14 @@ void cProjectileEntity::HandlePhysics(float a_Dt, cChunk & a_Chunk)
SetYawFromSpeed();
SetPitchFromSpeed();
- // DEBUG:
+ /*
LOGD("Projectile %d: pos {%.02f, %.02f, %.02f}, speed {%.02f, %.02f, %.02f}, rot {%.02f, %.02f}",
m_UniqueID,
GetPosX(), GetPosY(), GetPosZ(),
GetSpeedX(), GetSpeedY(), GetSpeedZ(),
GetYaw(), GetPitch()
);
+ */
}
@@ -446,7 +465,7 @@ bool cArrowEntity::CanPickup(const cPlayer & a_Player) const
-void cArrowEntity::OnHitSolidBlock(const Vector3d & a_HitPos, char a_HitFace)
+void cArrowEntity::OnHitSolidBlock(const Vector3d & a_HitPos, eBlockFace a_HitFace)
{
if (a_HitFace == BLOCK_FACE_NONE) { return; }
@@ -590,7 +609,7 @@ cThrownEggEntity::cThrownEggEntity(cEntity * a_Creator, double a_X, double a_Y,
-void cThrownEggEntity::OnHitSolidBlock(const Vector3d & a_HitPos, char a_HitFace)
+void cThrownEggEntity::OnHitSolidBlock(const Vector3d & a_HitPos, eBlockFace a_HitFace)
{
if (m_World->GetTickRandomNumber(7) == 1)
{
@@ -623,7 +642,7 @@ cThrownEnderPearlEntity::cThrownEnderPearlEntity(cEntity * a_Creator, double a_X
-void cThrownEnderPearlEntity::OnHitSolidBlock(const Vector3d & a_HitPos, char a_HitFace)
+void cThrownEnderPearlEntity::OnHitSolidBlock(const Vector3d & a_HitPos, eBlockFace a_HitFace)
{
// Teleport the creator here, make them take 5 damage:
if (m_Creator != NULL)
@@ -653,10 +672,8 @@ cThrownSnowballEntity::cThrownSnowballEntity(cEntity * a_Creator, double a_X, do
-void cThrownSnowballEntity::OnHitSolidBlock(const Vector3d & a_HitPos, char a_HitFace)
+void cThrownSnowballEntity::OnHitSolidBlock(const Vector3d & a_HitPos, eBlockFace a_HitFace)
{
- // TODO: Apply damage to certain mobs (blaze etc.) and anger all mobs
-
Destroy();
}
@@ -664,6 +681,30 @@ void cThrownSnowballEntity::OnHitSolidBlock(const Vector3d & a_HitPos, char a_Hi
+void cThrownSnowballEntity::OnHitEntity(cEntity & a_EntityHit, const Vector3d & a_HitPos)
+{
+ int TotalDamage = 0;
+ if (a_EntityHit.IsMob())
+ {
+ cMonster::eType MobType = ((cMonster &) a_EntityHit).GetMobType();
+ if (MobType == cMonster::mtBlaze)
+ {
+ TotalDamage = 3;
+ }
+ else if (MobType == cMonster::mtEnderDragon)
+ {
+ TotalDamage = 1;
+ }
+ }
+ a_EntityHit.TakeDamage(dtRangedAttack, this, TotalDamage, 1);
+
+ Destroy(true);
+}
+
+
+
+
+
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// cBottleOEnchantingEntity :
@@ -677,9 +718,11 @@ super(pkExpBottle, a_Creator, a_X, a_Y, a_Z, 0.25, 0.25)
-void cExpBottleEntity::OnHitSolidBlock(const Vector3d & a_HitPos, char a_HitFace)
+void cExpBottleEntity::OnHitSolidBlock(const Vector3d & a_HitPos, eBlockFace a_HitFace)
{
- // TODO: Spawn experience orbs
+ // Spawn an experience orb with a reward between 3 and 11.
+ m_World->BroadcastSoundParticleEffect(2002, POSX_TOINT, POSY_TOINT, POSZ_TOINT, 0);
+ m_World->SpawnExperienceOrb(GetPosX(), GetPosY(), GetPosZ(), 3 + m_World->GetTickRandomNumber(8));
Destroy();
}
@@ -691,8 +734,10 @@ void cExpBottleEntity::OnHitSolidBlock(const Vector3d & a_HitPos, char a_HitFace
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// cFireworkEntity :
-cFireworkEntity::cFireworkEntity(cEntity * a_Creator, double a_X, double a_Y, double a_Z) :
-super(pkFirework, a_Creator, a_X, a_Y, a_Z, 0.25, 0.25)
+cFireworkEntity::cFireworkEntity(cEntity * a_Creator, double a_X, double a_Y, double a_Z, const cItem & a_Item) :
+super(pkFirework, a_Creator, a_X, a_Y, a_Z, 0.25, 0.25),
+ m_ExplodeTimer(0),
+ m_FireworkItem(a_Item)
{
}
@@ -700,32 +745,20 @@ super(pkFirework, a_Creator, a_X, a_Y, a_Z, 0.25, 0.25)
-void cFireworkEntity::OnHitSolidBlock(const Vector3d & a_HitPos, char a_HitFace)
+void cFireworkEntity::HandlePhysics(float a_Dt, cChunk & a_Chunk)
{
- if ((a_HitFace != BLOCK_FACE_BOTTOM) && (a_HitFace != BLOCK_FACE_NONE))
+ int RelX = POSX_TOINT - a_Chunk.GetPosX() * cChunkDef::Width;
+ int RelZ = POSZ_TOINT - a_Chunk.GetPosZ() * cChunkDef::Width;
+ int PosY = POSY_TOINT;
+
+ if ((PosY < 0) || (PosY >= cChunkDef::Height))
{
- return;
+ goto setspeed;
}
- SetSpeed(0, 0, 0);
- SetPosition(GetPosX(), GetPosY() - 0.5, GetPosZ());
-
- std::cout << a_HitPos.x << " " << a_HitPos.y << " " << a_HitPos.z << std::endl;
-
- m_IsInGround = true;
-
- BroadcastMovementUpdate();
-}
-
-
-
-
-
-void cFireworkEntity::HandlePhysics(float a_Dt, cChunk & a_Chunk)
-{
if (m_IsInGround)
{
- if (a_Chunk.GetBlock((int)GetPosX(), (int)GetPosY() + 1, (int)GetPosZ()) == E_BLOCK_AIR)
+ if (a_Chunk.GetBlock(RelX, POSY_TOINT + 1, RelZ) == E_BLOCK_AIR)
{
m_IsInGround = false;
}
@@ -734,28 +767,35 @@ void cFireworkEntity::HandlePhysics(float a_Dt, cChunk & a_Chunk)
return;
}
}
+ else
+ {
+ if (a_Chunk.GetBlock(RelX, POSY_TOINT + 1, RelZ) != E_BLOCK_AIR)
+ {
+ OnHitSolidBlock(GetPosition(), BLOCK_FACE_YM);
+ return;
+ }
+ }
- Vector3d PerTickSpeed = GetSpeed() / 20;
- Vector3d Pos = GetPosition();
+setspeed:
+ AddSpeedY(1);
+ AddPosition(GetSpeed() * (a_Dt / 1000));
+}
- // Trace the tick's worth of movement as a line:
- Vector3d NextPos = Pos + PerTickSpeed;
- cProjectileTracerCallback TracerCallback(this);
- if (!cLineBlockTracer::Trace(*m_World, TracerCallback, Pos, NextPos))
+
+
+
+
+void cFireworkEntity::Tick(float a_Dt, cChunk & a_Chunk)
+{
+ super::Tick(a_Dt, a_Chunk);
+
+ if (m_ExplodeTimer == m_FireworkItem.m_FireworkItem.m_FlightTimeInTicks)
{
- // Something has been hit, abort all other processing
- return;
+ m_World->BroadcastEntityStatus(*this, ENTITY_STATUS_FIREWORK_EXPLODE);
+ Destroy();
}
- // The tracer also checks the blocks for slowdown blocks - water and lava - and stores it for later in its SlowdownCoeff
-
- // Update the position:
- SetPosition(NextPos);
- // Add slowdown and gravity effect to the speed:
- Vector3d NewSpeed(GetSpeed());
- NewSpeed.y += 2;
- NewSpeed *= TracerCallback.GetSlowdownCoeff();
- SetSpeed(NewSpeed);
+ m_ExplodeTimer++;
}
@@ -785,7 +825,7 @@ void cGhastFireballEntity::Explode(int a_BlockX, int a_BlockY, int a_BlockZ)
-void cGhastFireballEntity::OnHitSolidBlock(const Vector3d & a_HitPos, char a_HitFace)
+void cGhastFireballEntity::OnHitSolidBlock(const Vector3d & a_HitPos, eBlockFace a_HitFace)
{
Destroy();
Explode((int)floor(a_HitPos.x), (int)floor(a_HitPos.y), (int)floor(a_HitPos.z));
@@ -831,7 +871,7 @@ void cFireChargeEntity::Explode(int a_BlockX, int a_BlockY, int a_BlockZ)
-void cFireChargeEntity::OnHitSolidBlock(const Vector3d & a_HitPos, char a_HitFace)
+void cFireChargeEntity::OnHitSolidBlock(const Vector3d & a_HitPos, eBlockFace a_HitFace)
{
Destroy();
Explode((int)floor(a_HitPos.x), (int)floor(a_HitPos.y), (int)floor(a_HitPos.z));