2012-06-14 09:06:06 -04:00
# pragma once
2013-08-19 05:39:13 -04:00
# include "../Entities/Pawn.h"
2012-09-23 16:53:08 -04:00
# include "../Defines.h"
# include "../BlockID.h"
2012-09-23 18:09:57 -04:00
# include "../Item.h"
2014-02-23 13:44:58 -05:00
# include "../Enchantments.h"
2014-09-17 13:40:10 -04:00
# include "MonsterTypes.h"
2012-06-14 09:06:06 -04:00
class cClientHandle ;
2013-08-16 04:48:19 -04:00
class cWorld ;
2012-06-14 09:06:06 -04:00
2015-04-29 12:24:14 -04:00
// Fwd: cPath
enum class ePathFinderStatus ;
class cPath ;
2012-06-14 09:06:06 -04:00
2012-12-21 06:04:08 -05:00
// tolua_begin
class cMonster :
public cPawn
{
typedef cPawn super ;
2012-06-14 09:06:06 -04:00
public :
2013-09-07 14:02:50 -04:00
enum eFamily
{
2014-07-17 16:15:34 -04:00
mfHostile = 0 , // Spider, Zombies ...
mfPassive = 1 , // Cows, Pigs
mfAmbient = 2 , // Bats
2014-12-18 13:30:32 -05:00
mfWater = 3 , // Squid, Guardian
2013-09-18 17:17:43 -04:00
2014-04-25 23:49:55 -04:00
mfNoSpawn ,
2014-07-17 16:15:34 -04:00
mfUnhandled , // Nothing. Be sure this is the last and the others are in order
2013-08-16 04:48:19 -04:00
} ;
2014-10-11 22:39:55 -04:00
2012-12-21 06:04:08 -05:00
// tolua_end
2014-10-11 22:39:55 -04:00
2013-10-20 07:25:56 -04:00
enum MState { ATTACKING , IDLE , CHASING , ESCAPING } m_EMState ;
2014-07-19 08:53:41 -04:00
enum MPersonality { PASSIVE , AGGRESSIVE , COWARDLY } m_EMPersonality ;
2014-10-11 22:39:55 -04:00
2012-12-22 04:39:13 -05:00
/** Creates the mob object.
2014-07-18 03:57:34 -04:00
If a_ConfigName is not empty , the configuration is loaded using GetMonsterConfig ( )
a_MobType is the type of the mob ( also used in the protocol ( http : //wiki.vg/Entities#Mobs 2012_12_22))
a_SoundHurt and a_SoundDeath are assigned into m_SoundHurt and m_SoundDeath , respectively
2012-12-22 04:39:13 -05:00
*/
2014-09-17 13:40:10 -04:00
cMonster ( const AString & a_ConfigName , eMonsterType a_MobType , const AString & a_SoundHurt , const AString & a_SoundDeath , double a_Width , double a_Height ) ;
2012-06-14 09:06:06 -04:00
2014-07-22 18:36:13 -04:00
CLASS_PROTODEF ( cMonster )
2014-10-11 22:39:55 -04:00
2012-08-24 03:58:26 -04:00
virtual void SpawnOn ( cClientHandle & a_ClientHandle ) override ;
2012-06-14 09:06:06 -04:00
2015-01-11 16:12:26 -05:00
virtual void Tick ( std : : chrono : : milliseconds a_Dt , cChunk & a_Chunk ) override ;
2012-06-14 09:06:06 -04:00
2014-04-25 18:32:30 -04:00
virtual bool DoTakeDamage ( TakeDamageInfo & a_TDI ) override ;
2014-10-11 22:39:55 -04:00
2014-07-04 05:55:09 -04:00
virtual void KilledBy ( TakeDamageInfo & a_TDI ) override ;
2012-06-14 09:06:06 -04:00
2014-09-01 15:05:45 -04:00
virtual void OnRightClicked ( cPlayer & a_Player ) override ;
2015-05-03 13:56:37 -04:00
/** Engage pathfinder and tell it to calculate a path to a given position, and move the mobile accordingly
Currently , the mob will only start moving to a new position after the position it is currently going to is reached . */
2014-07-17 16:15:34 -04:00
virtual void MoveToPosition ( const Vector3d & a_Position ) ; // tolua_export
2014-10-11 22:39:55 -04:00
2013-10-20 04:23:30 -04:00
// tolua_begin
2014-09-26 17:56:20 -04:00
eMonsterType GetMobType ( void ) const { return m_MobType ; }
2013-09-10 09:09:45 -04:00
eFamily GetMobFamily ( void ) const ;
2013-10-20 04:23:30 -04:00
// tolua_end
2014-10-11 22:39:55 -04:00
2013-04-13 17:02:10 -04:00
virtual void CheckEventSeePlayer ( void ) ;
virtual void EventSeePlayer ( cEntity * a_Player ) ;
2014-10-11 22:39:55 -04:00
2015-07-31 10:49:10 -04:00
/** Reads the monster configuration for the specified monster name and assigns it to this object. */
2012-12-22 04:39:13 -05:00
void GetMonsterConfig ( const AString & a_Name ) ;
2014-10-11 22:39:55 -04:00
2014-06-08 21:44:20 -04:00
/** Returns whether this mob is undead (skeleton, zombie, etc.) */
2014-07-19 17:35:35 -04:00
virtual bool IsUndead ( void ) ;
2014-10-11 22:39:55 -04:00
2012-12-22 05:15:53 -05:00
virtual void EventLosePlayer ( void ) ;
2013-04-13 17:02:10 -04:00
virtual void CheckEventLostPlayer ( void ) ;
2014-10-11 22:39:55 -04:00
2015-01-16 09:38:21 -05:00
virtual void InStateIdle ( std : : chrono : : milliseconds a_Dt ) ;
virtual void InStateChasing ( std : : chrono : : milliseconds a_Dt ) ;
virtual void InStateEscaping ( std : : chrono : : milliseconds a_Dt ) ;
2014-10-11 22:39:55 -04:00
int GetAttackRate ( ) { return static_cast < int > ( m_AttackRate ) ; }
2014-01-24 14:57:32 -05:00
void SetAttackRate ( float a_AttackRate ) { m_AttackRate = a_AttackRate ; }
void SetAttackRange ( int a_AttackRange ) { m_AttackRange = a_AttackRange ; }
void SetAttackDamage ( int a_AttackDamage ) { m_AttackDamage = a_AttackDamage ; }
void SetSightDistance ( int a_SightDistance ) { m_SightDistance = a_SightDistance ; }
2014-10-11 22:39:55 -04:00
2014-02-23 13:44:58 -05:00
float GetDropChanceWeapon ( ) { return m_DropChanceWeapon ; }
float GetDropChanceHelmet ( ) { return m_DropChanceHelmet ; }
float GetDropChanceChestplate ( ) { return m_DropChanceChestplate ; }
float GetDropChanceLeggings ( ) { return m_DropChanceLeggings ; }
float GetDropChanceBoots ( ) { return m_DropChanceBoots ; }
bool CanPickUpLoot ( ) { return m_CanPickUpLoot ; }
void SetDropChanceWeapon ( float a_DropChanceWeapon ) { m_DropChanceWeapon = a_DropChanceWeapon ; }
void SetDropChanceHelmet ( float a_DropChanceHelmet ) { m_DropChanceHelmet = a_DropChanceHelmet ; }
void SetDropChanceChestplate ( float a_DropChanceChestplate ) { m_DropChanceChestplate = a_DropChanceChestplate ; }
void SetDropChanceLeggings ( float a_DropChanceLeggings ) { m_DropChanceLeggings = a_DropChanceLeggings ; }
void SetDropChanceBoots ( float a_DropChanceBoots ) { m_DropChanceBoots = a_DropChanceBoots ; }
void SetCanPickUpLoot ( bool a_CanPickUpLoot ) { m_CanPickUpLoot = a_CanPickUpLoot ; }
2014-10-11 22:39:55 -04:00
2015-07-31 10:49:10 -04:00
/** Sets whether the mob burns in daylight. Only evaluated at next burn-decision tick */
2013-09-17 15:57:35 -04:00
void SetBurnsInDaylight ( bool a_BurnsInDaylight ) { m_BurnsInDaylight = a_BurnsInDaylight ; }
2013-10-09 16:02:59 -04:00
2014-09-02 14:10:41 -04:00
double GetRelativeWalkSpeed ( void ) const { return m_RelativeWalkSpeed ; } // tolua_export
void SetRelativeWalkSpeed ( double a_WalkSpeed ) { m_RelativeWalkSpeed = a_WalkSpeed ; } // tolua_export
2014-08-30 06:44:54 -04:00
2013-10-09 16:02:59 -04:00
// Overridables to handle ageable mobs
virtual bool IsTame ( void ) const { return false ; }
virtual bool IsSitting ( void ) const { return false ; }
2014-10-11 22:39:55 -04:00
2015-07-16 09:06:54 -04:00
// tolua_begin
2015-07-12 12:00:56 -04:00
bool IsBaby ( void ) const { return m_Age < 0 ; }
char GetAge ( void ) const { return m_Age ; }
void SetAge ( char a_Age ) { m_Age = a_Age ; }
2015-07-16 09:06:54 -04:00
// tolua_end
2015-07-12 12:00:56 -04:00
2013-10-20 07:25:56 -04:00
// tolua_begin
2014-09-01 14:12:56 -04:00
/** Returns true if the monster has a custom name. */
bool HasCustomName ( void ) const { return ! m_CustomName . empty ( ) ; }
2014-09-02 13:20:59 -04:00
/** Gets the custom name of the monster. If no custom name is set, the function returns an empty string. */
2014-09-01 14:12:56 -04:00
const AString & GetCustomName ( void ) const { return m_CustomName ; }
2014-09-02 13:12:35 -04:00
/** Sets the custom name of the monster. You see the name over the monster.
If you want to disable the custom name , simply set an empty string . */
2014-09-01 14:12:56 -04:00
void SetCustomName ( const AString & a_CustomName ) ;
/** Is the custom name of this monster always visible? If not, you only see the name when you sight the mob. */
bool IsCustomNameAlwaysVisible ( void ) const { return m_CustomNameAlwaysVisible ; }
/** Sets the custom name visiblity of this monster.
2014-09-02 13:20:59 -04:00
If it ' s false , you only see the name when you sight the mob . If it ' s true , you always see the custom name . */
2014-09-01 14:12:56 -04:00
void SetCustomNameAlwaysVisible ( bool a_CustomNameAlwaysVisible ) ;
2014-11-29 09:20:44 -05:00
/** Translates MobType enum to a string, empty string if unknown */
2014-09-17 13:40:10 -04:00
static AString MobTypeToString ( eMonsterType a_MobType ) ;
2014-10-11 22:39:55 -04:00
2014-12-01 08:58:13 -05:00
/** Translates MobType enum to the vanilla name of the mob, empty string if unknown. */
2014-11-29 09:20:44 -05:00
static AString MobTypeToVanillaName ( eMonsterType a_MobType ) ;
/** Translates MobType string to the enum, mtInvalidType if not recognized */
2014-09-17 13:40:10 -04:00
static eMonsterType StringToMobType ( const AString & a_MobTypeName ) ;
2014-10-11 22:39:55 -04:00
2014-11-29 09:20:44 -05:00
/** Returns the mob family based on the type */
2014-09-17 13:40:10 -04:00
static eFamily FamilyFromType ( eMonsterType a_MobType ) ;
2013-10-20 08:00:45 -04:00
2014-11-29 09:20:44 -05:00
/** Returns the spawn delay (number of game ticks between spawn attempts) for the given mob family */
2013-10-24 10:45:13 -04:00
static int GetSpawnDelay ( cMonster : : eFamily a_MobFamily ) ;
2013-10-20 07:25:56 -04:00
// tolua_end
2014-10-11 22:39:55 -04:00
2013-10-20 07:25:56 -04:00
/** Creates a new object of the specified mob.
a_MobType is the type of the mob to be created
2013-11-10 15:48:12 -05:00
Asserts and returns null if mob type is not specified
2013-10-20 07:25:56 -04:00
*/
2014-09-17 13:40:10 -04:00
static cMonster * NewMonsterFromType ( eMonsterType a_MobType ) ;
2013-10-20 07:25:56 -04:00
2012-06-14 09:06:06 -04:00
protected :
2014-10-11 22:39:55 -04:00
2014-01-24 14:57:32 -05:00
/** A pointer to the entity this mobile is aiming to reach */
2012-12-21 06:04:08 -05:00
cEntity * m_Target ;
2015-04-29 12:24:14 -04:00
cPath * m_Path ; // TODO unique ptr
2015-05-03 13:56:37 -04:00
/** Stores if mobile is currently moving towards the ultimate, final destination */
2015-04-29 12:24:14 -04:00
bool m_IsFollowingPath ;
2015-05-03 13:56:37 -04:00
2015-07-11 15:40:03 -04:00
/** Stores if pathfinder is being used - set when final destination is set, and unset when stopped moving to final destination */
bool m_PathfinderActivated ;
2015-05-05 03:04:41 -04:00
/* If 0, will give up reaching the next m_NextWayPointPosition and will re-compute path. */
2015-04-29 12:24:14 -04:00
int m_GiveUpCounter ;
2015-05-03 13:56:37 -04:00
2014-01-24 14:57:32 -05:00
/** Coordinates of the next position that should be reached */
2015-05-05 03:04:41 -04:00
Vector3d m_NextWayPointPosition ;
2015-05-03 13:56:37 -04:00
2014-01-24 14:57:32 -05:00
/** Coordinates for the ultimate, final destination. */
Vector3d m_FinalDestination ;
2014-10-11 22:39:55 -04:00
2014-11-15 15:45:57 -05:00
/** Finds the lowest non-air block position (not the highest, as cWorld::GetHeight does)
If current Y is nonsolid , goes down to try to find a solid block , then returns that + 1
If current Y is solid , goes up to find first nonsolid block , and returns that .
If no suitable position is found , returns cChunkDef : : Height . */
2014-01-24 14:57:32 -05:00
int FindFirstNonAirBlockPosition ( double a_PosX , double a_PosZ ) ;
2014-11-15 15:45:57 -05:00
2015-05-28 10:45:47 -04:00
/** Returns if the ultimate, final destination has been reached. */
bool ReachedFinalDestination ( void ) { return ( ( m_FinalDestination - GetPosition ( ) ) . Length ( ) < GetWidth ( ) / 2 ) ; }
/** Returns whether or not the target is close enough for attack. */
bool TargetIsInRange ( void ) { return ( ( m_FinalDestination - GetPosition ( ) ) . SqrLength ( ) < ( m_AttackRange * m_AttackRange ) ) ; }
2015-05-03 13:56:37 -04:00
2015-05-05 03:04:41 -04:00
/** Returns if the intermediate waypoint of m_NextWayPointPosition has been reached */
bool ReachedNextWaypoint ( void ) { return ( ( m_NextWayPointPosition - GetPosition ( ) ) . SqrLength ( ) < 0.25 ) ; }
2015-05-03 13:56:37 -04:00
2015-05-28 10:45:47 -04:00
/** Returns if a monster can reach a given height by jumping. */
2014-01-25 09:42:26 -05:00
inline bool DoesPosYRequireJump ( int a_PosY )
{
2014-04-17 13:50:25 -04:00
return ( ( a_PosY > POSY_TOINT ) & & ( a_PosY = = POSY_TOINT + 1 ) ) ;
2014-01-24 16:55:04 -05:00
}
2014-01-24 14:57:32 -05:00
2015-05-05 03:04:41 -04:00
/** Finds the next place to go by calculating a path and setting the m_NextWayPointPosition variable for the next block to head to
2015-05-03 13:56:37 -04:00
This is based on the ultimate , final destination and the current position , as well as the A * algorithm , and any environmental hazards
2015-05-05 03:04:41 -04:00
Returns if a path is ready , and therefore if the mob should move to m_NextWayPointPosition
2015-05-03 13:56:37 -04:00
*/
bool TickPathFinding ( cChunk & a_Chunk ) ;
2015-05-06 10:23:07 -04:00
/** Move in a straight line to the next waypoint in the path, will jump if needed. */
2015-05-03 13:56:37 -04:00
void MoveToWayPoint ( cChunk & a_Chunk ) ;
2014-01-24 14:57:32 -05:00
2015-05-06 10:23:07 -04:00
/** Ensures the destination is not buried underground or under water. Also ensures the destination is not in the air.
Only the Y coordinate of m_FinalDestination might be changed .
1. If m_FinalDestination is the position of a water block , m_FinalDestination ' s Y will be modified to point to the heighest water block in the pool in the current column .
2. If m_FinalDestination is the position of a solid , m_FinalDestination ' s Y will be modified to point to the first airblock above the solid in the current column .
3. If m_FinalDestination is the position of an air block , Y will keep decreasing until hitting either a solid or water .
Now either 1 or 2 is performed . */
bool EnsureProperDestination ( cChunk & a_Chunk ) ;
2015-05-03 13:56:37 -04:00
/** Resets a pathfinding task, be it due to failure or something else
Resets the pathfinder . If m_IsFollowingPath is true , TickPathFinding starts a brand new path .
Should only be called by the pathfinder , cMonster : : Tick or StopMovingToPosition . */
2015-05-01 13:34:24 -04:00
void ResetPathFinding ( void ) ;
2015-05-03 13:56:37 -04:00
/** Stops pathfinding
Calls ResetPathFinding and sets m_IsFollowingPath to false */
void StopMovingToPosition ( ) ;
2015-05-09 03:25:09 -04:00
/** Sets the body yaw and head yaw / pitch based on next / ultimate destinations */
2014-01-24 14:57:32 -05:00
void SetPitchAndYawFromDestination ( void ) ;
2014-01-25 14:02:13 -05:00
virtual void HandleFalling ( void ) ;
int m_LastGroundHeight ;
2015-05-02 14:22:28 -04:00
int m_JumpCoolDown ;
2014-01-25 14:02:13 -05:00
2015-01-16 09:38:21 -05:00
std : : chrono : : milliseconds m_IdleInterval ;
std : : chrono : : milliseconds m_DestroyTimer ;
2012-06-14 09:06:06 -04:00
2014-09-17 13:40:10 -04:00
eMonsterType m_MobType ;
2014-09-01 14:12:56 -04:00
AString m_CustomName ;
bool m_CustomNameAlwaysVisible ;
2012-06-14 09:06:06 -04:00
2012-12-21 13:05:34 -05:00
AString m_SoundHurt ;
AString m_SoundDeath ;
2014-07-17 16:50:58 -04:00
float m_AttackRate ;
2014-01-24 14:57:32 -05:00
int m_AttackDamage ;
int m_AttackRange ;
2012-06-14 09:06:06 -04:00
float m_AttackInterval ;
2014-01-24 14:57:32 -05:00
int m_SightDistance ;
2014-10-11 22:39:55 -04:00
2014-02-23 13:44:58 -05:00
float m_DropChanceWeapon ;
float m_DropChanceHelmet ;
float m_DropChanceChestplate ;
float m_DropChanceLeggings ;
float m_DropChanceBoots ;
bool m_CanPickUpLoot ;
2015-04-29 12:24:14 -04:00
int m_TicksSinceLastDamaged ; // How many ticks ago we were last damaged by a player?
2014-10-11 22:39:55 -04:00
2015-05-01 13:34:24 -04:00
void HandleDaylightBurning ( cChunk & a_Chunk , bool WouldBurn ) ;
2015-04-29 12:24:14 -04:00
bool WouldBurnAt ( Vector3d a_Location , cChunk & a_Chunk ) ;
2013-09-05 16:40:08 -04:00
bool m_BurnsInDaylight ;
2014-09-02 14:10:41 -04:00
double m_RelativeWalkSpeed ;
2014-08-30 06:44:54 -04:00
2015-07-12 12:00:56 -04:00
char m_Age ;
2015-07-31 10:49:10 -04:00
/** Adds a random number of a_Item between a_Min and a_Max to itemdrops a_Drops */
2014-07-17 16:50:58 -04:00
void AddRandomDropItem ( cItems & a_Drops , unsigned int a_Min , unsigned int a_Max , short a_Item , short a_ItemHealth = 0 ) ;
2014-10-11 22:39:55 -04:00
2015-07-31 10:49:10 -04:00
/** Adds a item a_Item with the chance of a_Chance (in percent) to itemdrops a_Drops */
2014-07-17 16:50:58 -04:00
void AddRandomUncommonDropItem ( cItems & a_Drops , float a_Chance , short a_Item , short a_ItemHealth = 0 ) ;
2014-10-11 22:39:55 -04:00
2015-07-31 10:49:10 -04:00
/** Adds one rare item out of the list of rare items a_Items modified by the looting level a_LootingLevel(I-III or custom) to the itemdrop a_Drops */
2015-05-19 14:32:10 -04:00
void AddRandomRareDropItem ( cItems & a_Drops , cItems & a_Items , unsigned int a_LootingLevel ) ;
2014-10-11 22:39:55 -04:00
2015-07-31 10:49:10 -04:00
/** Adds armor that is equipped with the chance saved in m_DropChance[...] (this will be greter than 1 if picked up or 0.085 + (0.01 per LootingLevel) if born with) to the drop */
2015-05-19 14:32:10 -04:00
void AddRandomArmorDropItem ( cItems & a_Drops , unsigned int a_LootingLevel ) ;
2014-10-11 22:39:55 -04:00
2015-07-31 10:49:10 -04:00
/** Adds weapon that is equipped with the chance saved in m_DropChance[...] (this will be greter than 1 if picked up or 0.085 + (0.01 per LootingLevel) if born with) to the drop */
2015-05-19 14:32:10 -04:00
void AddRandomWeaponDropItem ( cItems & a_Drops , unsigned int a_LootingLevel ) ;
2012-06-14 09:06:06 -04:00
2014-10-11 22:39:55 -04:00
} ; // tolua_export