#pragma once #include "../Item.h" #include "../Vector3.h" // Place this macro in the public section of each cEntity descendant class and you're done :) #define CLASS_PROTODEF(classname) \ virtual bool IsA(const char * a_ClassName) const override\ { \ return ((strcmp(a_ClassName, #classname) == 0) || super::IsA(a_ClassName)); \ } \ virtual const char * GetClass(void) const override \ { \ return #classname; \ } \ static const char * GetClassStatic(void) \ { \ return #classname; \ } \ virtual const char * GetParentClass(void) const override \ { \ return super::GetClass(); \ } #define POSX_TOINT (int)floor(GetPosX()) #define POSY_TOINT (int)floor(GetPosY()) #define POSZ_TOINT (int)floor(GetPosZ()) #define POS_TOINT Vector3i(POSXTOINT, POSYTOINT, POSZTOINT) #define GET_AND_VERIFY_CURRENT_CHUNK(ChunkVarName, X, Z) cChunk * ChunkVarName = a_Chunk.GetNeighborChunk(X, Z); if ((ChunkVarName == NULL) || !ChunkVarName->IsValid()) { return; } class cWorld; class cClientHandle; class cPlayer; class cChunk; // tolua_begin struct TakeDamageInfo { eDamageType DamageType; // Where does the damage come from? Being hit / on fire / contact with cactus / ... cEntity * Attacker; // The attacking entity; valid only for dtAttack int RawDamage; // What damage would the receiver get without any armor. Usually: attacker mob type + weapons int FinalDamage; // What actual damage will be received. Usually: m_RawDamage minus armor Vector3d Knockback; // The amount and direction of knockback received from the damage // TODO: Effects - list of effects that the hit is causing. Unknown representation yet } ; // tolua_end // tolua_begin class cEntity { public: enum eEntityType { etEntity, // For all other types etEnderCrystal, etPlayer, etPickup, etMonster, etFallingBlock, etMinecart, etBoat, etTNT, etProjectile, etExpOrb, etFloater, etItemFrame, etPainting, // Common variations etMob = etMonster, // DEPRECATED, use etMonster instead! } ; // tolua_end enum eEntityStatus { // TODO: Investiagate 0, 1, and 5 as Wiki.vg is not certain // Entity becomes coloured red esGenericHurt = 2, // Entity plays death animation (entity falls to ground) esGenericDead = 3, // Iron Golem plays attack animation (arms lift and fall) esIronGolemAttacking = 4, // Wolf taming particles spawn (smoke) esWolfTaming = 6, // Wolf tamed particles spawn (hearts) esWolfTamed = 7, // Wolf plays water removal animation (shaking and water particles) esWolfDryingWater = 8, // Informs client that eating was accepted esPlayerEatingAccepted = 9, // Sheep plays eating animation (head lowers to ground) esSheepEating = 10, // Iron Golem holds gift to villager children esIronGolemGivingPlant = 11, // Villager spawns heart particles esVillagerBreeding = 12, // Villager spawns thunderclound particles esVillagerAngry = 13, // Villager spawns green crosses esVillagerHappy = 14, // Witch spawns magic particle (TODO: investigation into what this is) esWitchMagicking = 15, // It seems 16 (zombie conversion) is now done with metadata // Informs client to explode a firework based on its metadata esFireworkExploding = 17, } ; enum { FIRE_TICKS_PER_DAMAGE = 10, ///< How many ticks to wait between damaging an entity when it stands in fire FIRE_DAMAGE = 1, ///< How much damage to deal when standing in fire LAVA_TICKS_PER_DAMAGE = 10, ///< How many ticks to wait between damaging an entity when it stands in lava LAVA_DAMAGE = 5, ///< How much damage to deal when standing in lava BURN_TICKS_PER_DAMAGE = 20, ///< How many ticks to wait between damaging an entity when it is burning BURN_DAMAGE = 1, ///< How much damage to deal when the entity is burning BURN_TICKS = 200, ///< How long to keep an entity burning after it has stood in lava / fire MAX_AIR_LEVEL = 300, ///< Maximum air an entity can have DROWNING_TICKS = 20, ///< Number of ticks per heart of damage VOID_BOUNDARY = -46 ///< At what position Y to begin applying void damage } ; cEntity(eEntityType a_EntityType, double a_X, double a_Y, double a_Z, double a_Width, double a_Height); virtual ~cEntity(); /// Spawns the entity in the world; returns true if spawned, false if not (plugin disallowed) virtual bool Initialize(cWorld * a_World); // tolua_begin eEntityType GetEntityType(void) const { return m_EntityType; } bool IsEnderCrystal(void) const { return (m_EntityType == etEnderCrystal); } bool IsPlayer (void) const { return (m_EntityType == etPlayer); } bool IsPickup (void) const { return (m_EntityType == etPickup); } bool IsMob (void) const { return (m_EntityType == etMonster); } bool IsFallingBlock(void) const { return (m_EntityType == etFallingBlock); } bool IsMinecart (void) const { return (m_EntityType == etMinecart); } bool IsBoat (void) const { return (m_EntityType == etBoat); } bool IsTNT (void) const { return (m_EntityType == etTNT); } bool IsProjectile (void) const { return (m_EntityType == etProjectile); } bool IsExpOrb (void) const { return (m_EntityType == etExpOrb); } bool IsFloater (void) const { return (m_EntityType == etFloater); } bool IsItemFrame (void) const { return (m_EntityType == etItemFrame); } bool IsPainting (void) const { return (m_EntityType == etPainting); } /// Returns true if the entity is of the specified class or a subclass (cPawn's IsA("cEntity") returns true) virtual bool IsA(const char * a_ClassName) const; /// Returns the topmost class name for the object virtual const char * GetClass(void) const; // Returns the class name of this class static const char * GetClassStatic(void); /// Returns the topmost class's parent class name for the object. cEntity returns an empty string (no parent). virtual const char * GetParentClass(void) const; cWorld * GetWorld(void) const { return m_World; } double GetHeadYaw (void) const { return m_HeadYaw; } // In degrees double GetHeight (void) const { return m_Height; } double GetMass (void) const { return m_Mass; } const Vector3d & GetPosition (void) const { return m_Pos; } double GetPosX (void) const { return m_Pos.x; } double GetPosY (void) const { return m_Pos.y; } double GetPosZ (void) const { return m_Pos.z; } const Vector3d & GetRot (void) const { return m_Rot; } // OBSOLETE, use individual GetYaw(), GetPitch, GetRoll() components double GetYaw (void) const { return m_Rot.x; } // In degrees, [-180, +180) double GetPitch (void) const { return m_Rot.y; } // In degrees, [-180, +180), but normal client clips to [-90, +90] double GetRoll (void) const { return m_Rot.z; } // In degrees, unused in current client Vector3d GetLookVector(void) const; const Vector3d & GetSpeed (void) const { return m_Speed; } double GetSpeedX (void) const { return m_Speed.x; } double GetSpeedY (void) const { return m_Speed.y; } double GetSpeedZ (void) const { return m_Speed.z; } double GetWidth (void) const { return m_Width; } int GetChunkX(void) const {return (int)floor(m_Pos.x / cChunkDef::Width); } int GetChunkZ(void) const {return (int)floor(m_Pos.z / cChunkDef::Width); } void SetHeadYaw (double a_HeadYaw); void SetHeight (double a_Height); void SetMass (double a_Mass); void SetPosX (double a_PosX); 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 SetRot (const Vector3f & a_Rot); // OBSOLETE, use individual SetYaw(), SetPitch(), SetRoll() components void SetYaw (double a_Yaw); // In degrees, normalizes to [-180, +180) void SetPitch (double a_Pitch); // In degrees, normalizes to [-180, +180) void SetRoll (double a_Roll); // In degrees, normalizes to [-180, +180) void SetSpeed (double a_SpeedX, double a_SpeedY, double a_SpeedZ); void SetSpeed (const Vector3d & a_Speed) { SetSpeed(a_Speed.x, a_Speed.y, a_Speed.z); } void SetSpeedX (double a_SpeedX); void SetSpeedY (double a_SpeedY); void SetSpeedZ (double a_SpeedZ); void SetWidth (double a_Width); void AddPosX (double a_AddPosX); void AddPosY (double a_AddPosY); void AddPosZ (double a_AddPosZ); void AddPosition(double a_AddPosX, double a_AddPosY, double a_AddPosZ); void AddPosition(const Vector3d & a_AddPos) { AddPosition(a_AddPos.x,a_AddPos.y,a_AddPos.z);} void AddSpeed (double a_AddSpeedX, double a_AddSpeedY, double a_AddSpeedZ); void AddSpeed (const Vector3d & a_AddSpeed) { AddSpeed(a_AddSpeed.x,a_AddSpeed.y,a_AddSpeed.z);} void AddSpeedX (double a_AddSpeedX); void AddSpeedY (double a_AddSpeedY); void AddSpeedZ (double a_AddSpeedZ); virtual void HandleSpeedFromAttachee(float a_Forward, float a_Sideways); void SteerVehicle(float a_Forward, float a_Sideways); inline int GetUniqueID(void) const { return m_UniqueID; } inline bool IsDestroyed(void) const { return !m_IsInitialized; } /// Schedules the entity for destroying; if a_ShouldBroadcast is set to true, broadcasts the DestroyEntity packet void Destroy(bool a_ShouldBroadcast = true); /// Makes this pawn take damage from an attack by a_Attacker. Damage values are calculated automatically and DoTakeDamage() called void TakeDamage(cEntity & a_Attacker); /// Makes this entity take the specified damage. The final damage is calculated using current armor, then DoTakeDamage() called void TakeDamage(eDamageType a_DamageType, cEntity * a_Attacker, int a_RawDamage, double a_KnockbackAmount); /// Makes this entity take the specified damage. The values are packed into a TDI, knockback calculated, then sent through DoTakeDamage() void TakeDamage(eDamageType a_DamageType, cEntity * a_Attacker, int a_RawDamage, int a_FinalDamage, double a_KnockbackAmount); float GetGravity(void) const { return m_Gravity; } void SetGravity(float a_Gravity) { m_Gravity = a_Gravity; } /// Sets the rotation to match the speed vector (entity goes "face-forward") void SetYawFromSpeed(void); /// Sets the pitch to match the speed vector (entity gies "face-forward") void SetPitchFromSpeed(void); // tolua_end /// Makes this entity take damage specified in the a_TDI. The TDI is sent through plugins first, then applied virtual void DoTakeDamage(TakeDamageInfo & a_TDI); // tolua_begin /// Returns the hitpoints that this pawn can deal to a_Receiver using its equipped items virtual int GetRawDamageAgainst(const cEntity & a_Receiver); /// Returns the hitpoints out of a_RawDamage that the currently equipped armor would cover virtual int GetArmorCoverAgainst(const cEntity * a_Attacker, eDamageType a_DamageType, int a_RawDamage); /// Returns the knockback amount that the currently equipped items would cause to a_Receiver on a hit virtual double GetKnockbackAmountAgainst(const cEntity & a_Receiver); /// Returns the curently equipped weapon; empty item if none virtual cItem GetEquippedWeapon(void) const { return cItem(); } /// Returns the currently equipped helmet; empty item if none virtual cItem GetEquippedHelmet(void) const { return cItem(); } /// Returns the currently equipped chestplate; empty item if none virtual cItem GetEquippedChestplate(void) const { return cItem(); } /// Returns the currently equipped leggings; empty item if none virtual cItem GetEquippedLeggings(void) const { return cItem(); } /// Returns the currently equipped boots; empty item if none virtual cItem GetEquippedBoots(void) const { return cItem(); } /// Called when the health drops below zero. a_Killer may be NULL (environmental damage) virtual void KilledBy(cEntity * a_Killer); /// Heals the specified amount of HPs void Heal(int a_HitPoints); /// Returns the health of this entity int GetHealth(void) const { return m_Health; } /// Sets the health of this entity; doesn't broadcast any hurt animation void SetHealth(int a_Health); // tolua_end virtual void Tick(float a_Dt, cChunk & a_Chunk); /// Handles the physics of the entity - updates position based on speed, updates speed based on environment virtual void HandlePhysics(float a_Dt, cChunk & a_Chunk); /// Updates the state related to this entity being on fire virtual void TickBurning(cChunk & a_Chunk); /// Handles when the entity is in the void virtual void TickInVoid(cChunk & a_Chunk); /// Called when the entity starts burning virtual void OnStartedBurning(void); /// Called when the entity finishes burning virtual void OnFinishedBurning(void); // tolua_begin /// Sets the maximum value for the health void SetMaxHealth(int a_MaxHealth); int GetMaxHealth(void) const { return m_MaxHealth; } /// Puts the entity on fire for the specified amount of ticks void StartBurning(int a_TicksLeftBurning); /// Stops the entity from burning, resets all burning timers void StopBurning(void); // tolua_end /** 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() */ virtual void SpawnOn(cClientHandle & a_Client) = 0; // tolua_begin /// Teleports to the entity specified virtual void TeleportToEntity(cEntity & a_Entity); /// Teleports to the coordinates specified virtual void TeleportToCoords(double a_PosX, double a_PosY, double a_PosZ); // tolua_end /// Updates clients of changes in the entity. virtual void BroadcastMovementUpdate(const cClientHandle * a_Exclude = NULL); /// Attaches to the specified entity; detaches from any previous one first void AttachTo(cEntity * a_AttachTo); /// Detaches from the currently attached entity, if any virtual void Detach(void); /// Makes sure head yaw is not over the specified range. void WrapHeadYaw(); /// Makes sure rotation is not over the specified range. void WrapRotation(); /// Makes speed is not over 20. Max speed is 20 blocks / second void WrapSpeed(); // tolua_begin // COMMON metadata flags; descendants may override the defaults: virtual bool IsOnFire (void) const {return (m_TicksLeftBurning > 0); } virtual bool IsCrouched (void) const {return false; } virtual bool IsRiding (void) const {return false; } virtual bool IsSprinting(void) const {return false; } virtual bool IsRclking (void) const {return false; } virtual bool IsInvisible(void) const { return false; } /** Returns whether the player is swimming or not */ virtual bool IsSwimming(void) const{ return m_IsSwimming; } /** Return whether the player is under water or not */ virtual bool IsSubmerged(void) const{ return m_IsSubmerged; } /** Gets remaining air of a monster */ int GetAirLevel(void) const { return m_AirLevel; } // tolua_end /// Called when the specified player right-clicks this entity virtual void OnRightClicked(cPlayer &) {}; /// Returns the list of drops for this pawn when it is killed. May check a_Killer for special handling (sword of looting etc.). Called from KilledBy(). virtual void GetDrops(cItems & a_Drops, cEntity * a_Killer = NULL) { UNUSED(a_Drops); UNUSED(a_Killer); } protected: static cCriticalSection m_CSCount; static int m_EntityCount; int m_UniqueID; int m_Health; int m_MaxHealth; /// The entity to which this entity is attached (vehicle), NULL if none cEntity * m_AttachedTo; /// The entity which is attached to this entity (rider), NULL if none cEntity * m_Attachee; // Flags that signal that we haven't updated the clients with the latest. bool m_bDirtyHead; bool m_bDirtyOrientation; bool m_bDirtyPosition; bool m_bDirtySpeed; bool m_bOnGround; float m_Gravity; // Last Position. double m_LastPosX, m_LastPosY, m_LastPosZ; // This variables keep track of the last time a packet was sent Int64 m_TimeLastTeleportPacket, m_TimeLastMoveReltPacket, m_TimeLastSpeedPacket; // In ticks bool m_IsInitialized; // Is set to true when it's initialized, until it's destroyed (Initialize() till Destroy() ) eEntityType m_EntityType; cWorld * m_World; /// Time, in ticks, since the last damage dealt by being on fire. Valid only if on fire (IsOnFire()) int m_TicksSinceLastBurnDamage; /// Time, in ticks, since the last damage dealt by standing in lava. Reset to zero when moving out of lava. int m_TicksSinceLastLavaDamage; /// Time, in ticks, since the last damage dealt by standing in fire. Reset to zero when moving out of fire. int m_TicksSinceLastFireDamage; /// Time, in ticks, until the entity extinguishes its fire int m_TicksLeftBurning; /// Time, in ticks, since the last damage dealt by the void. Reset to zero when moving out of the void. int m_TicksSinceLastVoidDamage; virtual void Destroyed(void) {} // Called after the entity has been destroyed void SetWorld(cWorld * a_World) { m_World = a_World; } /** Called in each tick to handle air-related processing i.e. drowning */ virtual void HandleAir(); /** Called once per tick to set IsSwimming and IsSubmerged */ virtual void SetSwimState(cChunk & a_Chunk); /** If an entity is currently swimming in or submerged under water */ bool m_IsSwimming, m_IsSubmerged; /** Air level of a mobile */ int m_AirLevel; int m_AirTickTimer; private: // Measured in degrees, [-180, +180) double m_HeadYaw; // Measured in meter/second (m/s) Vector3d m_Speed; // Measured in degrees, [-180, +180) Vector3d m_Rot; /// Position of the entity's XZ center and Y bottom Vector3d m_Pos; // Measured in meter / second Vector3d m_WaterSpeed; // Measured in Kilograms (Kg) double m_Mass; /// Width of the entity, in the XZ plane. Since entities are represented as cylinders, this is more of a diameter. double m_Width; /// Height of the entity (Y axis) double m_Height; } ; // tolua_export typedef std::list cEntityList;