Arrows deal damage.
Still needs some tweaks, they hit the shooter most of the time.
This commit is contained in:
parent
4f04724cfd
commit
a884fbb919
@ -8,6 +8,9 @@
|
|||||||
#include "../ClientHandle.h"
|
#include "../ClientHandle.h"
|
||||||
#include "Player.h"
|
#include "Player.h"
|
||||||
#include "../LineBlockTracer.h"
|
#include "../LineBlockTracer.h"
|
||||||
|
#include "../BoundingBox.h"
|
||||||
|
#include "../ChunkMap.h"
|
||||||
|
#include "../Chunk.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -63,6 +66,82 @@ protected:
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// cProjectileEntityCollisionCallback:
|
||||||
|
|
||||||
|
class cProjectileEntityCollisionCallback :
|
||||||
|
public cEntityCallback
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
cProjectileEntityCollisionCallback(cProjectileEntity * a_Projectile, const Vector3d & a_Pos, const Vector3d & a_NextPos) :
|
||||||
|
m_Projectile(a_Projectile),
|
||||||
|
m_Pos(a_Pos),
|
||||||
|
m_NextPos(a_NextPos),
|
||||||
|
m_MinCoeff(1),
|
||||||
|
m_HitEntity(NULL)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
virtual bool Item(cEntity * a_Entity) override
|
||||||
|
{
|
||||||
|
if (a_Entity == m_Projectile)
|
||||||
|
{
|
||||||
|
// Self-colision
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
cBoundingBox EntBox(a_Entity->GetPosition(), a_Entity->GetWidth() / 2, a_Entity->GetHeight());
|
||||||
|
|
||||||
|
// 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;
|
||||||
|
EntBox.Expand(m_Projectile->GetWidth() / 2, m_Projectile->GetHeight() / 2, m_Projectile->GetWidth() / 2);
|
||||||
|
if (!EntBox.CalcLineIntersection(m_Pos, m_NextPos, LineCoeff, Face))
|
||||||
|
{
|
||||||
|
// No intersection whatsoever
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: Some entities don't interact with the projectiles (pickups, falling blocks)
|
||||||
|
// TODO: Allow plugins to interfere about which entities can be hit
|
||||||
|
|
||||||
|
if (LineCoeff < m_MinCoeff)
|
||||||
|
{
|
||||||
|
// The entity is closer than anything we've stored so far, replace it as the potential victim
|
||||||
|
m_MinCoeff = LineCoeff;
|
||||||
|
m_HitEntity = a_Entity;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Don't break the enumeration, we want all the entities
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns the nearest entity that was hit, after the enumeration has been completed
|
||||||
|
cEntity * GetHitEntity(void) const { return m_HitEntity; }
|
||||||
|
|
||||||
|
/// Returns the line coeff where the hit was encountered, after the enumeration has been completed
|
||||||
|
double GetMinCoeff(void) const { return m_MinCoeff; }
|
||||||
|
|
||||||
|
/// Returns true if the callback has encountered a true hit
|
||||||
|
bool HasHit(void) const { return (m_MinCoeff < 1); }
|
||||||
|
|
||||||
|
protected:
|
||||||
|
cProjectileEntity * m_Projectile;
|
||||||
|
const Vector3d & m_Pos;
|
||||||
|
const Vector3d & m_NextPos;
|
||||||
|
double m_MinCoeff; // The coefficient of the nearest hit on the Pos line
|
||||||
|
|
||||||
|
// Although it's bad(tm) to store entity ptrs from a callback, we can afford it here, because the entire callback
|
||||||
|
// is processed inside the tick thread, so the entities won't be removed in between the calls and the final processing
|
||||||
|
cEntity * m_HitEntity; // The nearest hit entity
|
||||||
|
} ;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
// cProjectileEntity:
|
// cProjectileEntity:
|
||||||
|
|
||||||
@ -192,17 +271,39 @@ void cProjectileEntity::HandlePhysics(float a_Dt, cChunk & a_Chunk)
|
|||||||
// Trace the tick's worth of movement as a line:
|
// Trace the tick's worth of movement as a line:
|
||||||
Vector3d NextPos = Pos + PerTickSpeed;
|
Vector3d NextPos = Pos + PerTickSpeed;
|
||||||
cProjectileTracerCallback TracerCallback(this);
|
cProjectileTracerCallback TracerCallback(this);
|
||||||
if (cLineBlockTracer::Trace(*m_World, TracerCallback, Pos, NextPos))
|
if (!cLineBlockTracer::Trace(*m_World, TracerCallback, Pos, NextPos))
|
||||||
{
|
{
|
||||||
// Nothing in the way, update the position
|
// Something has been hit, abort all other processing
|
||||||
SetPosition(NextPos);
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Test for entity collisions:
|
||||||
|
cProjectileEntityCollisionCallback EntityCollisionCallback(this, Pos, NextPos);
|
||||||
|
a_Chunk.ForEachEntity(EntityCollisionCallback);
|
||||||
|
if (EntityCollisionCallback.HasHit())
|
||||||
|
{
|
||||||
|
// An entity was hit:
|
||||||
|
// DEBUG:
|
||||||
|
Vector3d HitPos = Pos + (NextPos - Pos) * EntityCollisionCallback.GetMinCoeff();
|
||||||
|
LOGD("Projectile %d has hit an entity %d (%s) at {%.02f, %.02f, %.02f} (coeff %.03f)",
|
||||||
|
m_UniqueID,
|
||||||
|
EntityCollisionCallback.GetHitEntity()->GetUniqueID(),
|
||||||
|
EntityCollisionCallback.GetHitEntity()->GetClass(),
|
||||||
|
HitPos.x, HitPos.y, HitPos.z,
|
||||||
|
EntityCollisionCallback.GetMinCoeff()
|
||||||
|
);
|
||||||
|
OnHitEntity(*(EntityCollisionCallback.GetHitEntity()));
|
||||||
|
}
|
||||||
|
// TODO: Test the entities in the neighboring chunks, too
|
||||||
|
|
||||||
|
// Update the position:
|
||||||
|
SetPosition(NextPos);
|
||||||
|
|
||||||
// Add gravity effect to the vertical speed component:
|
// Add gravity effect to the vertical speed component:
|
||||||
SetSpeedY(GetSpeedY() + m_Gravity / 20);
|
SetSpeedY(GetSpeedY() + m_Gravity / 20);
|
||||||
|
|
||||||
// DEBUG:
|
// DEBUG:
|
||||||
LOGD("Arrow %d: pos {%.02f, %.02f, %.02f}, speed {%.02f, %.02f, %.02f}",
|
LOGD("Projectile %d: pos {%.02f, %.02f, %.02f}, speed {%.02f, %.02f, %.02f}",
|
||||||
m_UniqueID,
|
m_UniqueID,
|
||||||
GetPosX(), GetPosY(), GetPosZ(),
|
GetPosX(), GetPosY(), GetPosZ(),
|
||||||
GetSpeedX(), GetSpeedY(), GetSpeedZ()
|
GetSpeedX(), GetSpeedY(), GetSpeedZ()
|
||||||
@ -277,6 +378,24 @@ void cArrowEntity::SpawnOn(cClientHandle & a_Client)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void cArrowEntity::OnHitEntity(cEntity & a_EntityHit)
|
||||||
|
{
|
||||||
|
if (!a_EntityHit.IsMob() && !a_EntityHit.IsMinecart() && !a_EntityHit.IsPlayer())
|
||||||
|
{
|
||||||
|
// Not an entity that interacts with an arrow
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: The damage dealt should be based on arrow speed in addition to the damage coeff
|
||||||
|
a_EntityHit.TakeDamage(dtRangedAttack, this, (int)(2.5 * m_DamageCoeff), 1);
|
||||||
|
|
||||||
|
Destroy();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
// cThrownEggEntity:
|
// cThrownEggEntity:
|
||||||
|
|
||||||
|
@ -50,6 +50,9 @@ public:
|
|||||||
/// Called by the physics blocktracer when the entity hits a solid block, the block's coords and the face hit is given
|
/// Called by the physics blocktracer when the entity hits a solid block, the block's coords and the face hit is given
|
||||||
virtual void OnHitSolidBlock(int a_BlockX, int a_BlockY, int a_BlockZ, char a_BlockFace);
|
virtual void OnHitSolidBlock(int a_BlockX, int a_BlockY, int a_BlockZ, char a_BlockFace);
|
||||||
|
|
||||||
|
/// Called by the physics blocktracer when the entity hits another entity
|
||||||
|
virtual void OnHitEntity(cEntity & a_EntityHit) {}
|
||||||
|
|
||||||
// tolua_begin
|
// tolua_begin
|
||||||
|
|
||||||
/// Returns the kind of the projectile (fast class identification)
|
/// Returns the kind of the projectile (fast class identification)
|
||||||
@ -140,6 +143,7 @@ protected:
|
|||||||
|
|
||||||
// cProjectileEntity overrides:
|
// cProjectileEntity overrides:
|
||||||
virtual void SpawnOn(cClientHandle & a_Client) override;
|
virtual void SpawnOn(cClientHandle & a_Client) override;
|
||||||
|
virtual void OnHitEntity(cEntity & a_EntityHit) override;
|
||||||
|
|
||||||
// tolua_begin
|
// tolua_begin
|
||||||
} ;
|
} ;
|
||||||
|
Loading…
Reference in New Issue
Block a user