From 73afb1507d2a0defda8a03f60030dc49bb53f94f Mon Sep 17 00:00:00 2001 From: madmaxoft Date: Thu, 22 Aug 2013 08:55:58 +0200 Subject: Added skeleton code for projectile spawning. --- source/Entities/Entity.h | 6 +-- source/Entities/ProjectileEntity.cpp | 79 ++++++++++++++++++++++++++++++++++++ source/Entities/ProjectileEntity.h | 26 ++++++++++-- 3 files changed, 105 insertions(+), 6 deletions(-) create mode 100644 source/Entities/ProjectileEntity.cpp (limited to 'source/Entities') diff --git a/source/Entities/Entity.h b/source/Entities/Entity.h index 820405cb9..dde3eb8c6 100644 --- a/source/Entities/Entity.h +++ b/source/Entities/Entity.h @@ -90,12 +90,13 @@ public: etPlayer, etPickup, etMonster, - etMob = etMonster, // DEPRECATED, use etMonster instead! etFallingBlock, etMinecart, etTNT, + etProjectile, // DEPRECATED older constants, left over for compatibility reasons (plugins) + etMob = etMonster, // DEPRECATED, use etMonster instead! eEntityType_Entity = etEntity, eEntityType_Player = etPlayer, eEntityType_Pickup = etPickup, @@ -276,9 +277,8 @@ public: /** Descendants override this function to send a command to the specified client to spawn the entity on the client. To spawn on all eligible clients, use cChunkMap::BroadcastSpawnEntity() - Needs to have a default implementation due to Lua bindings. */ - virtual void SpawnOn(cClientHandle & a_Client) {ASSERT(!"SpawnOn() unimplemented!"); } + virtual void SpawnOn(cClientHandle & a_Client) = 0; // tolua_begin diff --git a/source/Entities/ProjectileEntity.cpp b/source/Entities/ProjectileEntity.cpp new file mode 100644 index 000000000..93508e2f7 --- /dev/null +++ b/source/Entities/ProjectileEntity.cpp @@ -0,0 +1,79 @@ + +// ProjectileEntity.cpp + +// Implements the cProjectileEntity class representing the common base class for projectiles, as well as individual projectile types + +#include "Globals.h" +#include "ProjectileEntity.h" + + + + + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// cProjectileEntity: + +cProjectileEntity::cProjectileEntity(eKind a_Kind, cEntity * a_Creator, double a_X, double a_Y, double a_Z, double a_Width, double a_Height) : + super(etProjectile, a_X, a_Y, a_Z, a_Width, a_Height), + m_Creator(a_Creator) +{ +} + + + + + +cProjectileEntity::cProjectileEntity(eKind a_Kind, cEntity * a_Creator, const Vector3d & a_Pos, const Vector3d & a_Speed, double a_Width, double a_Height) : + super(etProjectile, a_Pos.x, a_Pos.y, a_Pos.z, a_Width, a_Height), + m_Creator(a_Creator) +{ + SetSpeed(a_Speed); +} + + + + + +cProjectileEntity * cProjectileEntity::Create(eKind a_Kind, cEntity * a_Creator, double a_X, double a_Y, double a_Z, const Vector3d * a_Speed) +{ + Vector3d Speed; + if (a_Speed != NULL) + { + Speed = *a_Speed; + } + + switch (a_Kind) + { + case pkArrow: return new cArrowEntity(a_Creator, a_X, a_Y, a_Z, Speed); + // TODO: the rest + } + + LOGWARNING("%s: Unknown kind: %d", __FUNCTION__, a_Kind); + return NULL; +} + + + + + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// cArrowEntity: + +cArrowEntity::cArrowEntity(cEntity * a_Creator, double a_X, double a_Y, double a_Z, const Vector3d a_Speed) : + super(pkArrow, a_Creator, a_X, a_Y, a_Z, 0.5, 0.5) +{ + SetSpeed(a_Speed); +} + + + + + +void cArrowEntity::SpawnOn(cClientHandle & a_Client) +{ + // TODO +} + + + + diff --git a/source/Entities/ProjectileEntity.h b/source/Entities/ProjectileEntity.h index 2e050068b..426b2ea84 100644 --- a/source/Entities/ProjectileEntity.h +++ b/source/Entities/ProjectileEntity.h @@ -1,7 +1,7 @@ // ProjectileEntity.h -// Declares the cProjectileEntity class representing the common base class for projectiles +// Declares the cProjectileEntity class representing the common base class for projectiles, as well as individual projectile types @@ -38,12 +38,21 @@ public: pkFishingFloat = 90, } ; + // tolua_end + cProjectileEntity(eKind a_Kind, cEntity * a_Creator, double a_X, double a_Y, double a_Z, double a_Width, double a_Height); cProjectileEntity(eKind a_Kind, cEntity * a_Creator, const Vector3d & a_Pos, const Vector3d & a_Speed, double a_Width, double a_Height); + static cProjectileEntity * Create(eKind a_Kind, cEntity * a_Creator, double a_X, double a_Y, double a_Z, const Vector3d * a_Speed = NULL); + /// Called by the physics blocktracer when the entity hits a solid block, the coords and the face hit is given virtual void OnHitSolidBlock(double a_BlockX, double a_BlockY, double a_BlockZ, char a_BlockFace) {}; + // tolua_begin + + /// Returns the entity who created this projectile; may be NULL + cEntity * GetCreator(void) { return m_Creator; } + protected: eKind m_Kind; @@ -58,9 +67,20 @@ protected: class cArrowEntity : public cProjectileEntity { + typedef cProjectileEntity super; + public: - cArrowEntity(cEntity * a_Creator, double a_X, double a_Y, double a_Z, double a_Width, double a_Height); - cArrowEntity(cEntity * a_Creator, const Vector3d & a_Pos, const Vector3d & a_Speed, double a_Width, double a_Height); + + // tolua_end + + cArrowEntity(cEntity * a_Creator, double a_X, double a_Y, double a_Z, const Vector3d a_Speed); + +protected: + + // cEntity overrides: + virtual void SpawnOn(cClientHandle & a_Client) override; + + // tolua_begin } ; // tolua_end -- cgit v1.2.3 From 806c0bf981eb7d33930bb0a3d9db3232c9683c11 Mon Sep 17 00:00:00 2001 From: madmaxoft Date: Thu, 22 Aug 2013 09:07:12 +0200 Subject: Arrows can spawn on the client. --- source/Entities/ProjectileEntity.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'source/Entities') diff --git a/source/Entities/ProjectileEntity.cpp b/source/Entities/ProjectileEntity.cpp index 93508e2f7..c6c5ecc71 100644 --- a/source/Entities/ProjectileEntity.cpp +++ b/source/Entities/ProjectileEntity.cpp @@ -5,6 +5,7 @@ #include "Globals.h" #include "ProjectileEntity.h" +#include "../ClientHandle.h" @@ -71,7 +72,7 @@ cArrowEntity::cArrowEntity(cEntity * a_Creator, double a_X, double a_Y, double a void cArrowEntity::SpawnOn(cClientHandle & a_Client) { - // TODO + a_Client.SendSpawnObject(*this, pkArrow, 0, 0, 0); } -- cgit v1.2.3 From d622267515c69d553267f362a68aedfd956cbc5b Mon Sep 17 00:00:00 2001 From: madmaxoft Date: Thu, 22 Aug 2013 22:31:15 +0200 Subject: Added a few basic fields to cProjectileEntity and cArrowEntity. --- source/Entities/ProjectileEntity.cpp | 30 ++++++++++++++++++++++- source/Entities/ProjectileEntity.h | 47 +++++++++++++++++++++++++++++++++--- 2 files changed, 73 insertions(+), 4 deletions(-) (limited to 'source/Entities') diff --git a/source/Entities/ProjectileEntity.cpp b/source/Entities/ProjectileEntity.cpp index c6c5ecc71..e87f72eed 100644 --- a/source/Entities/ProjectileEntity.cpp +++ b/source/Entities/ProjectileEntity.cpp @@ -16,6 +16,7 @@ cProjectileEntity::cProjectileEntity(eKind a_Kind, cEntity * a_Creator, double a_X, double a_Y, double a_Z, double a_Width, double a_Height) : super(etProjectile, a_X, a_Y, a_Z, a_Width, a_Height), + m_ProjectileKind(a_Kind), m_Creator(a_Creator) { } @@ -26,6 +27,7 @@ cProjectileEntity::cProjectileEntity(eKind a_Kind, cEntity * a_Creator, double a cProjectileEntity::cProjectileEntity(eKind a_Kind, cEntity * a_Creator, const Vector3d & a_Pos, const Vector3d & a_Speed, double a_Width, double a_Height) : super(etProjectile, a_Pos.x, a_Pos.y, a_Pos.z, a_Width, a_Height), + m_ProjectileKind(a_Kind), m_Creator(a_Creator) { SetSpeed(a_Speed); @@ -57,13 +59,39 @@ cProjectileEntity * cProjectileEntity::Create(eKind a_Kind, cEntity * a_Creator, +AString cProjectileEntity::GetMCAClassName(void) const +{ + switch (m_ProjectileKind) + { + case pkArrow: return "Arrow"; + case pkSnowball: return "Snowball"; + case pkEgg: return "Egg"; + case pkGhastFireball: return "Fireball"; + case pkFireCharge: return "SmallFireball"; + case pkEnderPearl: return "ThrownEnderPearl"; + case pkExpBottle: return "ThrownExpBottle"; + case pkSplashPotion: return "ThrownPotion"; + case pkWitherSkull: return "WitherSkull"; + case pkFishingFloat: return ""; // Unknown, perhaps MC doesn't save this? + } + ASSERT(!"Unhandled projectile entity kind!"); + return ""; +} + + + + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // cArrowEntity: cArrowEntity::cArrowEntity(cEntity * a_Creator, double a_X, double a_Y, double a_Z, const Vector3d a_Speed) : - super(pkArrow, a_Creator, a_X, a_Y, a_Z, 0.5, 0.5) + super(pkArrow, a_Creator, a_X, a_Y, a_Z, 0.5, 0.5), + m_PickupState(psNoPickup), + m_DamageCoeff(2) { SetSpeed(a_Speed); + SetMass(0.1); } diff --git a/source/Entities/ProjectileEntity.h b/source/Entities/ProjectileEntity.h index 426b2ea84..8c6791e2e 100644 --- a/source/Entities/ProjectileEntity.h +++ b/source/Entities/ProjectileEntity.h @@ -29,8 +29,8 @@ public: pkArrow = 60, pkSnowball = 61, pkEgg = 62, - pkGhastFireball = 63, // TODO: Unverified TypeID, check this in ProtoProxy - pkFireCharge = 64, // TODO: Unverified TypeID, check this in ProtoProxy + pkGhastFireball = 63, + pkFireCharge = 64, pkEnderPearl = 65, pkExpBottle = 75, pkSplashPotion = 73, @@ -50,14 +50,26 @@ public: // tolua_begin + /// Returns the kind of the projectile (fast class identification) + eKind GetProjectileKind(void) const { return m_ProjectileKind; } + /// Returns the entity who created this projectile; may be NULL cEntity * GetCreator(void) { return m_Creator; } + /// Returns the string that is used as the entity type (class name) in MCA files + AString GetMCAClassName(void) const; + + /// Returns true if the projectile has hit the ground and is stuck there + bool IsInGround(void) const { return m_IsInGround; } + protected: - eKind m_Kind; + eKind m_ProjectileKind; /// The entity who has created this projectile; may be NULL (e. g. for dispensers) cEntity * m_Creator; + + /// True if the projectile has hit the ground and is stuck there + bool m_IsInGround; } ; @@ -70,13 +82,42 @@ class cArrowEntity : typedef cProjectileEntity super; public: + /// Determines when the arrow can be picked up (depending on player gamemode). Corresponds to the MCA file "pickup" field + enum ePickupState + { + psNoPickup = 0, + psInSurvivalOrCreative = 1, + psInCreative = 2, + } ; // tolua_end + /// Creates a new arrow with psNoPickup state and default damage modifier coeff cArrowEntity(cEntity * a_Creator, double a_X, double a_Y, double a_Z, const Vector3d a_Speed); + /// Returns whether the arrow can be picked up by players + ePickupState GetPickupState(void) const { return m_PickupState; } + + /// Sets a new pickup state + void SetPickupState(ePickupState a_PickupState) { m_PickupState = a_PickupState; } + + /// Returns the damage modifier coeff. + double GetDamageCoeff(void) const { return m_DamageCoeff; } + + /// Sets the damage modifier coeff + void SetDamageCoeff(double a_DamageCoeff) { m_DamageCoeff = a_DamageCoeff; } + + /// Returns true if the specified player can pick the arrow up + bool CanPickup(const cPlayer & a_Player) const; + protected: + /// Determines when the arrow can be picked up by players + ePickupState m_PickupState; + + /// The coefficient applied to the damage that the arrow will deal, based on the bow enchantment. 2.0 for normal arrow + double m_DamageCoeff; + // cEntity overrides: virtual void SpawnOn(cClientHandle & a_Client) override; -- cgit v1.2.3 From a7447b4c7e890f550ed02431ba00ec909d4e2b88 Mon Sep 17 00:00:00 2001 From: madmaxoft Date: Sun, 25 Aug 2013 21:25:13 +0200 Subject: Moved entity spawning into cEntity::Initialize(). It has been called in every descendant anyway, so it's better this way - reduced duplicate code. --- source/Entities/Entity.cpp | 4 ++++ source/Entities/FallingBlock.cpp | 14 -------------- source/Entities/FallingBlock.h | 1 - source/Entities/Minecart.cpp | 14 -------------- source/Entities/Minecart.h | 1 - source/Entities/Pickup.cpp | 14 -------------- source/Entities/Pickup.h | 2 -- source/Entities/TNTEntity.cpp | 14 -------------- source/Entities/TNTEntity.h | 1 - 9 files changed, 4 insertions(+), 61 deletions(-) (limited to 'source/Entities') diff --git a/source/Entities/Entity.cpp b/source/Entities/Entity.cpp index 19a65ef4e..65860118a 100644 --- a/source/Entities/Entity.cpp +++ b/source/Entities/Entity.cpp @@ -144,6 +144,10 @@ bool cEntity::Initialize(cWorld * a_World) m_World->AddEntity(this); cPluginManager::Get()->CallHookSpawnedEntity(*a_World, *this); + + // Spawn the entity on the clients: + a_World->BroadcastSpawnEntity(*this); + return true; } diff --git a/source/Entities/FallingBlock.cpp b/source/Entities/FallingBlock.cpp index 237327975..9fcd9ac80 100644 --- a/source/Entities/FallingBlock.cpp +++ b/source/Entities/FallingBlock.cpp @@ -22,20 +22,6 @@ cFallingBlock::cFallingBlock(const Vector3i & a_BlockPosition, BLOCKTYPE a_Block -bool cFallingBlock::Initialize(cWorld * a_World) -{ - if (super::Initialize(a_World)) - { - a_World->BroadcastSpawnEntity(*this); - return true; - } - return false; -} - - - - - void cFallingBlock::SpawnOn(cClientHandle & a_ClientHandle) { a_ClientHandle.SendSpawnFallingBlock(*this); diff --git a/source/Entities/FallingBlock.h b/source/Entities/FallingBlock.h index 13931f061..5ba9909bb 100644 --- a/source/Entities/FallingBlock.h +++ b/source/Entities/FallingBlock.h @@ -29,7 +29,6 @@ public: NIBBLETYPE GetBlockMeta(void) const { return m_BlockMeta; } // cEntity overrides: - virtual bool Initialize(cWorld * a_World) override; virtual void SpawnOn(cClientHandle & a_ClientHandle) override; virtual void Tick(float a_Dt, cChunk & a_Chunk) override; diff --git a/source/Entities/Minecart.cpp b/source/Entities/Minecart.cpp index 3e6069237..808579582 100644 --- a/source/Entities/Minecart.cpp +++ b/source/Entities/Minecart.cpp @@ -22,20 +22,6 @@ cMinecart::cMinecart(ePayload a_Payload, double a_X, double a_Y, double a_Z) : -bool cMinecart::Initialize(cWorld * a_World) -{ - if (super::Initialize(a_World)) - { - a_World->BroadcastSpawnEntity(*this); - return true; - } - return false; -} - - - - - void cMinecart::SpawnOn(cClientHandle & a_ClientHandle) { char Type = 0; diff --git a/source/Entities/Minecart.h b/source/Entities/Minecart.h index 91336673d..c1a0e84a0 100644 --- a/source/Entities/Minecart.h +++ b/source/Entities/Minecart.h @@ -35,7 +35,6 @@ public: } ; // cEntity overrides: - virtual bool Initialize(cWorld * a_World) override; virtual void SpawnOn(cClientHandle & a_ClientHandle) override; virtual void Tick(float a_Dt, cChunk & a_Chunk) override; diff --git a/source/Entities/Pickup.cpp b/source/Entities/Pickup.cpp index c8f36d503..9b388366a 100644 --- a/source/Entities/Pickup.cpp +++ b/source/Entities/Pickup.cpp @@ -40,20 +40,6 @@ cPickup::cPickup(int a_MicroPosX, int a_MicroPosY, int a_MicroPosZ, const cItem -bool cPickup::Initialize(cWorld * a_World) -{ - if (super::Initialize(a_World)) - { - a_World->BroadcastSpawnEntity(*this); - return true; - } - return false; -} - - - - - void cPickup::SpawnOn(cClientHandle & a_Client) { a_Client.SendPickupSpawn(*this); diff --git a/source/Entities/Pickup.h b/source/Entities/Pickup.h index b0323dd92..af6eaf3bb 100644 --- a/source/Entities/Pickup.h +++ b/source/Entities/Pickup.h @@ -26,8 +26,6 @@ public: cPickup(int a_MicroPosX, int a_MicroPosY, int a_MicroPosZ, const cItem & a_Item, float a_SpeedX = 0.f, float a_SpeedY = 0.f, float a_SpeedZ = 0.f); // tolua_export - virtual bool Initialize(cWorld * a_World) override; - cItem & GetItem(void) {return m_Item; } // tolua_export const cItem & GetItem(void) const {return m_Item; } diff --git a/source/Entities/TNTEntity.cpp b/source/Entities/TNTEntity.cpp index 43a0dea09..ad3d9ae0c 100644 --- a/source/Entities/TNTEntity.cpp +++ b/source/Entities/TNTEntity.cpp @@ -29,20 +29,6 @@ cTNTEntity::cTNTEntity(const Vector3d & a_Pos, double a_FuseTimeInSec) : -bool cTNTEntity::Initialize(cWorld * a_World) -{ - if (super::Initialize(a_World)) - { - a_World->BroadcastSpawnEntity(*this); - return true; - } - return false; -} - - - - - void cTNTEntity::SpawnOn(cClientHandle & a_ClientHandle) { a_ClientHandle.SendSpawnObject(*this, 50, 1, 0, 0); // 50 means TNT diff --git a/source/Entities/TNTEntity.h b/source/Entities/TNTEntity.h index ae6fc75e2..eb5040e8a 100644 --- a/source/Entities/TNTEntity.h +++ b/source/Entities/TNTEntity.h @@ -19,7 +19,6 @@ public: cTNTEntity(const Vector3d & a_Pos, double a_FuseTimeInSec); // cEntity overrides: - virtual bool Initialize(cWorld * a_World) override; virtual void SpawnOn(cClientHandle & a_ClientHandle) override; virtual void Tick(float a_Dt, cChunk & a_Chunk) override; -- cgit v1.2.3 From da3e24863274a80f4bda0251e678ec354c8d59e6 Mon Sep 17 00:00:00 2001 From: madmaxoft Date: Sun, 25 Aug 2013 21:31:35 +0200 Subject: Added a few API accessors to cArrowEntity. --- source/Entities/ProjectileEntity.cpp | 17 +++++++++++++++++ source/Entities/ProjectileEntity.h | 8 ++++++++ 2 files changed, 25 insertions(+) (limited to 'source/Entities') diff --git a/source/Entities/ProjectileEntity.cpp b/source/Entities/ProjectileEntity.cpp index e87f72eed..66d9409f5 100644 --- a/source/Entities/ProjectileEntity.cpp +++ b/source/Entities/ProjectileEntity.cpp @@ -6,6 +6,7 @@ #include "Globals.h" #include "ProjectileEntity.h" #include "../ClientHandle.h" +#include "Player.h" @@ -98,6 +99,22 @@ cArrowEntity::cArrowEntity(cEntity * a_Creator, double a_X, double a_Y, double a +bool cArrowEntity::CanPickup(const cPlayer & a_Player) const +{ + switch (m_PickupState) + { + case psNoPickup: return false; + case psInSurvivalOrCreative: return (a_Player.IsGameModeSurvival() || a_Player.IsGameModeCreative()); + case psInCreative: return a_Player.IsGameModeCreative(); + } + ASSERT(!"Unhandled pickup state"); + return false; +} + + + + + void cArrowEntity::SpawnOn(cClientHandle & a_Client) { a_Client.SendSpawnObject(*this, pkArrow, 0, 0, 0); diff --git a/source/Entities/ProjectileEntity.h b/source/Entities/ProjectileEntity.h index 8c6791e2e..cf107e15b 100644 --- a/source/Entities/ProjectileEntity.h +++ b/source/Entities/ProjectileEntity.h @@ -40,6 +40,8 @@ public: // tolua_end + CLASS_PROTODEF(cProjectileEntity); + cProjectileEntity(eKind a_Kind, cEntity * a_Creator, double a_X, double a_Y, double a_Z, double a_Width, double a_Height); cProjectileEntity(eKind a_Kind, cEntity * a_Creator, const Vector3d & a_Pos, const Vector3d & a_Speed, double a_Width, double a_Height); @@ -92,9 +94,13 @@ public: // tolua_end + CLASS_PROTODEF(cArrowEntity); + /// Creates a new arrow with psNoPickup state and default damage modifier coeff cArrowEntity(cEntity * a_Creator, double a_X, double a_Y, double a_Z, const Vector3d a_Speed); + // tolua_begin + /// Returns whether the arrow can be picked up by players ePickupState GetPickupState(void) const { return m_PickupState; } @@ -110,6 +116,8 @@ public: /// Returns true if the specified player can pick the arrow up bool CanPickup(const cPlayer & a_Player) const; + // tolua_end + protected: /// Determines when the arrow can be picked up by players -- cgit v1.2.3 From 71cfb8fcd2a037feef0a2a2efe8e1bcb81f7750c Mon Sep 17 00:00:00 2001 From: madmaxoft Date: Mon, 26 Aug 2013 22:27:28 +0200 Subject: Debug: arrow log their position in each tick --- source/Entities/Entity.cpp | 45 +++++++++++++++++++++--------------- source/Entities/ProjectileEntity.cpp | 12 ++++++++++ source/Entities/ProjectileEntity.h | 1 + 3 files changed, 39 insertions(+), 19 deletions(-) (limited to 'source/Entities') diff --git a/source/Entities/Entity.cpp b/source/Entities/Entity.cpp index 65860118a..608f5a73b 100644 --- a/source/Entities/Entity.cpp +++ b/source/Entities/Entity.cpp @@ -481,7 +481,7 @@ void cEntity::Tick(float a_Dt, cChunk & a_Chunk) void cEntity::HandlePhysics(float a_Dt, cChunk & a_Chunk) { // TODO Add collision detection with entities. - a_Dt /= 1000; + a_Dt /= 1000; // Convert from msec to sec Vector3d NextPos = Vector3d(GetPosX(),GetPosY(),GetPosZ()); Vector3d NextSpeed = Vector3d(GetSpeedX(),GetSpeedY(),GetSpeedZ()); int BlockX = (int) floor(NextPos.x); @@ -497,7 +497,7 @@ void cEntity::HandlePhysics(float a_Dt, cChunk & a_Chunk) } // Make sure we got the correct chunk and a valid one. No one ever knows... - cChunk * NextChunk = a_Chunk.GetNeighborChunk(BlockX,BlockZ); + cChunk * NextChunk = a_Chunk.GetNeighborChunk(BlockX, BlockZ); if (NextChunk != NULL) { int RelBlockX = BlockX - (NextChunk->GetPosX() * cChunkDef::Width); @@ -516,11 +516,12 @@ void cEntity::HandlePhysics(float a_Dt, cChunk & a_Chunk) } else { - //Push out entity. + // Push out entity. m_bOnGround = true; NextPos.y += 0.2; - LOGD("Entity #%d (%s) is inside a block at {%d,%d,%d}", - m_UniqueID, GetClass(), BlockX, BlockY, BlockZ); + LOGD("Entity #%d (%s) is inside a block at {%d, %d, %d}", + m_UniqueID, GetClass(), BlockX, BlockY, BlockZ + ); } if (!m_bOnGround) @@ -528,34 +529,40 @@ void cEntity::HandlePhysics(float a_Dt, cChunk & a_Chunk) float fallspeed; if (IsBlockWater(BlockIn)) { - fallspeed = -3.0f * a_Dt; //Fall slower in water. + fallspeed = -3.0f * a_Dt; // Fall slower in water. } else if (BlockIn == E_BLOCK_COBWEB) { - NextSpeed.y *= 0.05; //Reduce overall falling speed - fallspeed = 0; //No falling. + NextSpeed.y *= 0.05; // Reduce overall falling speed + fallspeed = 0; // No falling. } else { - //Normal gravity + // Normal gravity fallspeed = m_Gravity * a_Dt; } NextSpeed.y += fallspeed; } else { - //Friction + // Friction if (NextSpeed.SqrLength() > 0.0004f) { - NextSpeed.x *= 0.7f/(1+a_Dt); - if ( fabs(NextSpeed.x) < 0.05 ) NextSpeed.x = 0; - NextSpeed.z *= 0.7f/(1+a_Dt); - if ( fabs(NextSpeed.z) < 0.05 ) NextSpeed.z = 0; + NextSpeed.x *= 0.7f / (1 + a_Dt); + if (fabs(NextSpeed.x) < 0.05) + { + NextSpeed.x = 0; + } + NextSpeed.z *= 0.7f / (1 + a_Dt); + if (fabs(NextSpeed.z) < 0.05) + { + NextSpeed.z = 0; + } } } - //Adjust X and Z speed for COBWEB temporary. This speed modification should be handled inside block handlers since we - //might have different speed modifiers according to terrain. + // Adjust X and Z speed for COBWEB temporary. This speed modification should be handled inside block handlers since we + // might have different speed modifiers according to terrain. if (BlockIn == E_BLOCK_COBWEB) { NextSpeed.x *= 0.25; @@ -1032,9 +1039,9 @@ void cEntity::SetMass(double a_Mass) } else { - //Make sure that mass is not zero. 1g is the default because we - //have to choose a number. It's perfectly legal to have a mass - //less than 1g as long as is NOT equal or less than zero. + // Make sure that mass is not zero. 1g is the default because we + // have to choose a number. It's perfectly legal to have a mass + // less than 1g as long as is NOT equal or less than zero. m_Mass = 0.001; } } diff --git a/source/Entities/ProjectileEntity.cpp b/source/Entities/ProjectileEntity.cpp index 66d9409f5..552a61c42 100644 --- a/source/Entities/ProjectileEntity.cpp +++ b/source/Entities/ProjectileEntity.cpp @@ -115,6 +115,18 @@ bool cArrowEntity::CanPickup(const cPlayer & a_Player) const +void cArrowEntity::Tick(float a_Dt, cChunk & a_Chunk) +{ + super::Tick(a_Dt, a_Chunk); + + // DEBUG: + LOGD("Arrow %d: {%.02f, %.02f, %.02f}", m_UniqueID, GetPosX(), GetPosY(), GetPosZ()); +} + + + + + void cArrowEntity::SpawnOn(cClientHandle & a_Client) { a_Client.SendSpawnObject(*this, pkArrow, 0, 0, 0); diff --git a/source/Entities/ProjectileEntity.h b/source/Entities/ProjectileEntity.h index cf107e15b..345730d19 100644 --- a/source/Entities/ProjectileEntity.h +++ b/source/Entities/ProjectileEntity.h @@ -127,6 +127,7 @@ protected: double m_DamageCoeff; // cEntity overrides: + virtual void Tick(float a_Dt, cChunk & a_Chunk) override; virtual void SpawnOn(cClientHandle & a_Client) override; // tolua_begin -- cgit v1.2.3 From 49d69a02285a1b803bd650f1359c15cb0c57cfce Mon Sep 17 00:00:00 2001 From: madmaxoft Date: Mon, 26 Aug 2013 22:40:30 +0200 Subject: Debug logging for arrows improved --- source/Entities/ProjectileEntity.cpp | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) (limited to 'source/Entities') diff --git a/source/Entities/ProjectileEntity.cpp b/source/Entities/ProjectileEntity.cpp index 552a61c42..350cad95b 100644 --- a/source/Entities/ProjectileEntity.cpp +++ b/source/Entities/ProjectileEntity.cpp @@ -93,6 +93,9 @@ cArrowEntity::cArrowEntity(cEntity * a_Creator, double a_X, double a_Y, double a { SetSpeed(a_Speed); SetMass(0.1); + LOGD("Created arrow %d with speed {%.02f, %.02f, %.02f}", + m_UniqueID, GetSpeedX(), GetSpeedY(), GetSpeedZ() + ); } @@ -120,7 +123,11 @@ void cArrowEntity::Tick(float a_Dt, cChunk & a_Chunk) super::Tick(a_Dt, a_Chunk); // DEBUG: - LOGD("Arrow %d: {%.02f, %.02f, %.02f}", m_UniqueID, GetPosX(), GetPosY(), GetPosZ()); + LOGD("Arrow %d: pos {%.02f, %.02f, %.02f}, speed {%.02f, %.02f, %.02f}", + m_UniqueID, + GetPosX(), GetPosY(), GetPosZ(), + GetSpeedX(), GetSpeedY(), GetSpeedZ() + ); } -- cgit v1.2.3 From f260e9211fcba6f65fd131a34a75d288a10d5ebe Mon Sep 17 00:00:00 2001 From: madmaxoft Date: Tue, 27 Aug 2013 19:56:54 +0200 Subject: Entities fall 3x slower in water --- source/Entities/Entity.cpp | 2 +- source/Entities/Entity.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'source/Entities') diff --git a/source/Entities/Entity.cpp b/source/Entities/Entity.cpp index 608f5a73b..b936d8d73 100644 --- a/source/Entities/Entity.cpp +++ b/source/Entities/Entity.cpp @@ -529,7 +529,7 @@ void cEntity::HandlePhysics(float a_Dt, cChunk & a_Chunk) float fallspeed; if (IsBlockWater(BlockIn)) { - fallspeed = -3.0f * a_Dt; // Fall slower in water. + fallspeed = m_Gravity * a_Dt / 3; // Fall 3x slower in water. } else if (BlockIn == E_BLOCK_COBWEB) { diff --git a/source/Entities/Entity.h b/source/Entities/Entity.h index dde3eb8c6..f407cd2c1 100644 --- a/source/Entities/Entity.h +++ b/source/Entities/Entity.h @@ -163,7 +163,7 @@ public: void SetPosY (double a_PosY); void SetPosZ (double a_PosZ); void SetPosition(double a_PosX, double a_PosY, double a_PosZ); - void SetPosition(const Vector3d & a_Pos) { SetPosition(a_Pos.x,a_Pos.y,a_Pos.z);} + void SetPosition(const Vector3d & a_Pos) { SetPosition(a_Pos.x, a_Pos.y, a_Pos.z); } void SetRot (const Vector3f & a_Rot); void SetRotation(double a_Rotation); void SetPitch (double a_Pitch); -- cgit v1.2.3 From 6677a5e8ca15dcf796ba6b0dfe66d9d4b5ff8ca9 Mon Sep 17 00:00:00 2001 From: madmaxoft Date: Tue, 27 Aug 2013 19:57:37 +0200 Subject: Implemented basic physics for projectiles. --- source/Entities/ProjectileEntity.cpp | 147 ++++++++++++++++++++++++++++++----- source/Entities/ProjectileEntity.h | 9 ++- 2 files changed, 135 insertions(+), 21 deletions(-) (limited to 'source/Entities') diff --git a/source/Entities/ProjectileEntity.cpp b/source/Entities/ProjectileEntity.cpp index 350cad95b..4983943a9 100644 --- a/source/Entities/ProjectileEntity.cpp +++ b/source/Entities/ProjectileEntity.cpp @@ -7,6 +7,57 @@ #include "ProjectileEntity.h" #include "../ClientHandle.h" #include "Player.h" +#include "../LineBlockTracer.h" + + + + + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// cProjectileTracerCallback: + +class cProjectileTracerCallback : + public cBlockTracer::cCallbacks +{ +public: + cProjectileTracerCallback(cProjectileEntity * a_Projectile) : + m_Projectile(a_Projectile) + { + } + +protected: + cProjectileEntity * m_Projectile; + + virtual bool OnNextBlock(int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, char a_EntryFace) override + { + if (g_BlockIsSolid[a_BlockType]) + { + // The projectile hit a solid block + m_Projectile->OnHitSolidBlock(a_BlockX, a_BlockY, a_BlockZ, a_EntryFace); + return true; + } + + // Convey some special effects from special blocks: + switch (a_BlockType) + { + case E_BLOCK_LAVA: + case E_BLOCK_STATIONARY_LAVA: + { + m_Projectile->StartBurning(30); + break; + } + case E_BLOCK_WATER: + case E_BLOCK_STATIONARY_WATER: + { + m_Projectile->StopBurning(); + break; + } + } // switch (a_BlockType) + + // Continue tracing + return false; + } +} ; @@ -18,7 +69,8 @@ cProjectileEntity::cProjectileEntity(eKind a_Kind, cEntity * a_Creator, double a_X, double a_Y, double a_Z, double a_Width, double a_Height) : super(etProjectile, a_X, a_Y, a_Z, a_Width, a_Height), m_ProjectileKind(a_Kind), - m_Creator(a_Creator) + m_Creator(a_Creator), + m_IsInGround(false) { } @@ -29,7 +81,8 @@ cProjectileEntity::cProjectileEntity(eKind a_Kind, cEntity * a_Creator, double a cProjectileEntity::cProjectileEntity(eKind a_Kind, cEntity * a_Creator, const Vector3d & a_Pos, const Vector3d & a_Speed, double a_Width, double a_Height) : super(etProjectile, a_Pos.x, a_Pos.y, a_Pos.z, a_Width, a_Height), m_ProjectileKind(a_Kind), - m_Creator(a_Creator) + m_Creator(a_Creator), + m_IsInGround(false) { SetSpeed(a_Speed); } @@ -60,6 +113,35 @@ cProjectileEntity * cProjectileEntity::Create(eKind a_Kind, cEntity * a_Creator, +void cProjectileEntity::OnHitSolidBlock(int a_BlockX, int a_BlockY, int a_BlockZ, char a_BlockFace) +{ + // TODO: Set proper position based on what face was hit + switch (a_BlockFace) + { + case BLOCK_FACE_TOP: SetPosition(0.5 + a_BlockX, 1.0 + a_BlockY, 0.5 + a_BlockZ); break; + case BLOCK_FACE_BOTTOM: SetPosition(0.5 + a_BlockX, a_BlockY, 0.5 + a_BlockZ); break; + case BLOCK_FACE_EAST: SetPosition( a_BlockX, 0.5 + a_BlockY, 0.5 + a_BlockZ); break; + case BLOCK_FACE_WEST: SetPosition(1.0 + a_BlockX, 0.5 + a_BlockY, 0.5 + a_BlockZ); break; + case BLOCK_FACE_NORTH: SetPosition(0.5 + a_BlockX, 0.5 + a_BlockY, 1.0 + a_BlockZ); break; + case BLOCK_FACE_SOUTH: SetPosition(0.5 + a_BlockX, 0.5 + a_BlockY, a_BlockZ); break; + case BLOCK_FACE_NONE: SetPosition(0.5 + a_BlockX, 0.5 + a_BlockY, 0.5 + a_BlockZ); break; + } + SetSpeed(0, 0, 0); + + // DEBUG: + LOGD("Projectile %d: pos {%.02f, %.02f, %.02f}, hit solid block at face %d", + m_UniqueID, + GetPosX(), GetPosY(), GetPosZ(), + a_BlockFace + ); + + m_IsInGround = true; +} + + + + + AString cProjectileEntity::GetMCAClassName(void) const { switch (m_ProjectileKind) @@ -83,6 +165,51 @@ AString cProjectileEntity::GetMCAClassName(void) const +void cProjectileEntity::Tick(float a_Dt, cChunk & a_Chunk) +{ + super::Tick(a_Dt, a_Chunk); + BroadcastMovementUpdate(); +} + + + + + +void cProjectileEntity::HandlePhysics(float a_Dt, cChunk & a_Chunk) +{ + if (m_IsInGround) + { + // Already-grounded projectiles don't move at all + return; + } + + Vector3d PerTickSpeed = GetSpeed() / 20; + Vector3d Pos = GetPosition(); + + // 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)) + { + // Nothing in the way, update the position + SetPosition(NextPos); + } + + // Add gravity effect to the vertical speed component: + SetSpeedY(GetSpeedY() + m_Gravity / 20); + + // DEBUG: + LOGD("Arrow %d: pos {%.02f, %.02f, %.02f}, speed {%.02f, %.02f, %.02f}", + m_UniqueID, + GetPosX(), GetPosY(), GetPosZ(), + GetSpeedX(), GetSpeedY(), GetSpeedZ() + ); +} + + + + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // cArrowEntity: @@ -118,22 +245,6 @@ bool cArrowEntity::CanPickup(const cPlayer & a_Player) const -void cArrowEntity::Tick(float a_Dt, cChunk & a_Chunk) -{ - super::Tick(a_Dt, a_Chunk); - - // DEBUG: - LOGD("Arrow %d: pos {%.02f, %.02f, %.02f}, speed {%.02f, %.02f, %.02f}", - m_UniqueID, - GetPosX(), GetPosY(), GetPosZ(), - GetSpeedX(), GetSpeedY(), GetSpeedZ() - ); -} - - - - - void cArrowEntity::SpawnOn(cClientHandle & a_Client) { a_Client.SendSpawnObject(*this, pkArrow, 0, 0, 0); diff --git a/source/Entities/ProjectileEntity.h b/source/Entities/ProjectileEntity.h index 345730d19..7a97a2215 100644 --- a/source/Entities/ProjectileEntity.h +++ b/source/Entities/ProjectileEntity.h @@ -47,8 +47,8 @@ public: static cProjectileEntity * Create(eKind a_Kind, cEntity * a_Creator, double a_X, double a_Y, double a_Z, const Vector3d * a_Speed = NULL); - /// Called by the physics blocktracer when the entity hits a solid block, the coords and the face hit is given - virtual void OnHitSolidBlock(double a_BlockX, double a_BlockY, double a_BlockZ, char a_BlockFace) {}; + /// 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); // tolua_begin @@ -72,6 +72,10 @@ protected: /// True if the projectile has hit the ground and is stuck there bool m_IsInGround; + + // cEntity overrides: + virtual void Tick(float a_Dt, cChunk & a_Chunk) override; + virtual void HandlePhysics(float a_Dt, cChunk & a_Chunk) override; } ; @@ -127,7 +131,6 @@ protected: double m_DamageCoeff; // cEntity overrides: - virtual void Tick(float a_Dt, cChunk & a_Chunk) override; virtual void SpawnOn(cClientHandle & a_Client) override; // tolua_begin -- cgit v1.2.3 From 17ad4c2610f2c33d5b4a8b42b7d4b8fbda9ade32 Mon Sep 17 00:00:00 2001 From: madmaxoft Date: Fri, 30 Aug 2013 14:24:03 +0200 Subject: Shooting a bow kinda works. The arrow is released, but sometimes hits wrong blocks or disappears completely. --- source/Entities/Player.cpp | 44 ++++++++++++++++++++++++++++++++++++ source/Entities/Player.h | 15 ++++++++++++ source/Entities/ProjectileEntity.cpp | 41 +++++++++++++++++++++++++++++++++ source/Entities/ProjectileEntity.h | 9 ++++++++ 4 files changed, 109 insertions(+) (limited to 'source/Entities') diff --git a/source/Entities/Player.cpp b/source/Entities/Player.cpp index 119afbafc..0cb047933 100644 --- a/source/Entities/Player.cpp +++ b/source/Entities/Player.cpp @@ -64,6 +64,8 @@ cPlayer::cPlayer(cClientHandle* a_Client, const AString & a_PlayerName) , m_IsSwimming(false) , m_IsSubmerged(false) , m_EatingFinishTick(-1) + , m_IsChargingBow(false) + , m_BowCharge(0) { LOGD("Created a player object for \"%s\" @ \"%s\" at %p, ID %d", a_PlayerName.c_str(), a_Client->GetIPString().c_str(), @@ -213,6 +215,13 @@ void cPlayer::Tick(float a_Dt, cChunk & a_Chunk) // Handle air drowning stuff HandleAir(); + + // Handle charging the bow: + if (m_IsChargingBow) + { + m_BowCharge += 1; + LOGD("Player \"%s\" charging bow: %d", m_PlayerName.c_str(), m_BowCharge); + } if (m_bDirtyPosition) { @@ -253,6 +262,41 @@ void cPlayer::Tick(float a_Dt, cChunk & a_Chunk) +void cPlayer::StartChargingBow(void) +{ + LOGD("Player \"%s\" started charging their bow", m_PlayerName.c_str()); + m_IsChargingBow = true; + m_BowCharge = 0; +} + + + + + +int cPlayer::FinishChargingBow(void) +{ + LOGD("Player \"%s\" finished charging their bow at a charge of %d", m_PlayerName.c_str(), m_BowCharge); + int res = m_BowCharge; + m_IsChargingBow = false; + m_BowCharge = 0; + return res; +} + + + + + +void cPlayer::CancelChargingBow(void) +{ + LOGD("Player \"%s\" cancelled charging their bow at a charge of %d", m_PlayerName.c_str(), m_BowCharge); + m_IsChargingBow = false; + m_BowCharge = 0; +} + + + + + void cPlayer::SetTouchGround(bool a_bTouchGround) { // If just diff --git a/source/Entities/Player.h b/source/Entities/Player.h index 5dcce8421..4adf946db 100644 --- a/source/Entities/Player.h +++ b/source/Entities/Player.h @@ -62,6 +62,18 @@ public: /// Returns the currently equipped boots; empty item if none virtual cItem GetEquippedBoots(void) const override { return m_Inventory.GetEquippedBoots(); } + + /// Starts charging the equipped bow + void StartChargingBow(void); + + /// Finishes charging the current bow. Returns the number of ticks for which the bow has been charged + int FinishChargingBow(void); + + /// Cancels the current bow charging + void CancelChargingBow(void); + + /// Returns true if the player is currently charging the bow + bool IsChargingBox(void) const { return m_IsChargingBow; } void SetTouchGround( bool a_bTouchGround ); inline void SetStance( const double a_Stance ) { m_Stance = a_Stance; } @@ -351,6 +363,9 @@ protected: /// The world tick in which eating will be finished. -1 if not eating Int64 m_EatingFinishTick; + + bool m_IsChargingBow; + int m_BowCharge; virtual void Destroyed(void); diff --git a/source/Entities/ProjectileEntity.cpp b/source/Entities/ProjectileEntity.cpp index 4983943a9..f405e9aa4 100644 --- a/source/Entities/ProjectileEntity.cpp +++ b/source/Entities/ProjectileEntity.cpp @@ -229,6 +229,47 @@ cArrowEntity::cArrowEntity(cEntity * a_Creator, double a_X, double a_Y, double a +cArrowEntity::cArrowEntity(cPlayer & a_Player, double a_Force) : + super(pkArrow, &a_Player, PosFromPlayerPos(a_Player), SpeedFromPlayerLook(a_Player, a_Force), 0.5, 0.5), + m_PickupState(psInSurvivalOrCreative), + m_DamageCoeff(2) +{ +} + + + + + +Vector3d cArrowEntity::PosFromPlayerPos(const cPlayer & a_Player) +{ + Vector3d res = a_Player.GetEyePosition(); + + // Adjust the position to be just outside the player's bounding box: + res.x += 0.16 * cos(a_Player.GetPitch()); + res.y += -0.1; + res.z += 0.16 * sin(a_Player.GetPitch()); + + return res; +} + + + + + +Vector3d cArrowEntity::SpeedFromPlayerLook(const cPlayer & a_Player, double a_Force) +{ + Vector3d res = a_Player.GetLookVector(); + res.Normalize(); + + // TODO: Add a slight random change (+-0.0075 in each direction) + + return res * a_Force * 1.5 * 20; +} + + + + + bool cArrowEntity::CanPickup(const cPlayer & a_Player) const { switch (m_PickupState) diff --git a/source/Entities/ProjectileEntity.h b/source/Entities/ProjectileEntity.h index 7a97a2215..de0366014 100644 --- a/source/Entities/ProjectileEntity.h +++ b/source/Entities/ProjectileEntity.h @@ -103,8 +103,17 @@ public: /// Creates a new arrow with psNoPickup state and default damage modifier coeff cArrowEntity(cEntity * a_Creator, double a_X, double a_Y, double a_Z, const Vector3d a_Speed); + /// Creates a new arrow as shot by a player, initializes it from the player object + cArrowEntity(cPlayer & a_Player, double a_Force); + // tolua_begin + /// Returns the initial arrow position, as defined by the player eye position + adjustment. + static Vector3d PosFromPlayerPos(const cPlayer & a_Player); + + /// Returns the initial arrow speed, as defined by the player look vector and the force coefficient + static Vector3d SpeedFromPlayerLook(const cPlayer & a_Player, double a_Force); + /// Returns whether the arrow can be picked up by players ePickupState GetPickupState(void) const { return m_PickupState; } -- cgit v1.2.3