diff options
Diffstat (limited to 'src/Entities/ProjectileEntity.cpp')
-rw-r--r-- | src/Entities/ProjectileEntity.cpp | 158 |
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)); |