1
0

Refactored the TakeDamage API to take equipped weapon and armor into consideration (PvP untested)

http://forum.mc-server.org/showthread.php?tid=625

git-svn-id: http://mc-server.googlecode.com/svn/trunk@1087 0a769ca7-a7f5-676a-18bf-c427514a06d6
This commit is contained in:
madmaxoft@gmail.com 2012-12-21 11:04:08 +00:00
parent 231d6aed35
commit 912a1e7adc
62 changed files with 2532 additions and 1140 deletions

File diff suppressed because it is too large Load Diff

View File

@ -1,6 +1,6 @@
/* /*
** Lua binding: AllToLua ** Lua binding: AllToLua
** Generated automatically by tolua++-1.0.92 on 11/20/12 22:18:11. ** Generated automatically by tolua++-1.0.92 on 12/21/12 19:26:06.
*/ */
/* Exported function */ /* Exported function */

View File

@ -918,7 +918,7 @@ void cClientHandle::HandleUseEntity(int a_TargetEntityID, bool a_IsLeftClick)
if (!a_Entity->GetWorld()->IsPVPEnabled()) if (!a_Entity->GetWorld()->IsPVPEnabled())
{ {
// PVP is disabled // PVP is disabled
if (a_Entity->IsA("cPlayer") && Instigator->IsA("cPlayer")) if (a_Entity->IsA("cPlayer") && m_Attacker->IsA("cPlayer"))
{ {
// Player is hurting another player which is not allowed when PVP is disabled so ignore it // Player is hurting another player which is not allowed when PVP is disabled so ignore it
return true; return true;
@ -926,17 +926,15 @@ void cClientHandle::HandleUseEntity(int a_TargetEntityID, bool a_IsLeftClick)
} }
if (a_Entity->IsA("cPawn")) if (a_Entity->IsA("cPawn"))
{ {
reinterpret_cast<cPawn *>(a_Entity)->TakeDamage(Damage, Instigator); reinterpret_cast<cPawn *>(a_Entity)->TakeDamage(*m_Attacker);
} }
return true; return true;
} }
public: public:
int Damage; cPawn * m_Attacker;
cEntity * Instigator;
} Callback; } Callback;
Callback.Damage = 1; // TODO: Find proper damage from current item equipped Callback.m_Attacker = m_Player;
Callback.Instigator = m_Player;
cWorld * World = m_Player->GetWorld(); cWorld * World = m_Player->GetWorld();
World->DoWithEntityByID(a_TargetEntityID, Callback); World->DoWithEntityByID(a_TargetEntityID, Callback);

View File

@ -7,7 +7,7 @@
cBat::cBat() cBat::cBat(void)
{ {
m_MobType = 65; m_MobType = 65;
GetMonsterConfig("Bat"); GetMonsterConfig("Bat");
@ -17,29 +17,12 @@ cBat::cBat()
cBat::~cBat() bool cBat::IsA(const char * a_EntityType)
{ {
return ((strcmp(a_EntityType, "cBat") == 0) || super::IsA(a_EntityType));
} }
bool cBat::IsA( const char* a_EntityType )
{
if( strcmp( a_EntityType, "cBat" ) == 0 ) return true;
return cMonster::IsA( a_EntityType );
}
void cBat::KilledBy( cEntity* a_Killer )
{
cMonster::KilledBy( a_Killer );
}

View File

@ -1,14 +1,23 @@
#pragma once #pragma once
#include "PassiveMonster.h" #include "PassiveMonster.h"
class cBat : public cPassiveMonster
class cBat :
public cPassiveMonster
{ {
typedef cPassiveMonster super;
public: public:
cBat(); cBat(void);
~cBat();
virtual bool IsA(const char * a_EntityType) override;
} ;
virtual bool IsA( const char* a_EntityType );
virtual void KilledBy( cEntity* a_Killer );
};

View File

@ -7,7 +7,7 @@
cBlaze::cBlaze() cBlaze::cBlaze(void)
{ {
m_MobType = 61; m_MobType = 61;
GetMonsterConfig("Blaze"); GetMonsterConfig("Blaze");
@ -17,31 +17,18 @@ cBlaze::cBlaze()
cBlaze::~cBlaze() bool cBlaze::IsA(const char * a_EntityType)
{ {
return ((strcmp(a_EntityType, "cBlaze") == 0) || super::IsA(a_EntityType));
} }
bool cBlaze::IsA( const char* a_EntityType ) void cBlaze::GetDrops(cItems & a_Drops, cPawn * a_Killer)
{ {
if( strcmp( a_EntityType, "cBlaze" ) == 0 ) return true; AddRandomDropItem(a_Drops, 0, 1, E_ITEM_BLAZE_ROD);
return cMonster::IsA( a_EntityType );
}
void cBlaze::KilledBy( cEntity* a_Killer )
{
cItems Drops;
AddRandomDropItem(Drops, 0, 1, E_ITEM_BLAZE_ROD);
m_World->SpawnItemPickups(Drops, m_Pos.x, m_Pos.y, m_Pos.z);
cMonster::KilledBy( a_Killer );
} }

View File

@ -1,14 +1,25 @@
#pragma once #pragma once
#include "AggressiveMonster.h" #include "AggressiveMonster.h"
class cBlaze : public cAggressiveMonster
class cBlaze :
public cAggressiveMonster
{ {
typedef cAggressiveMonster super;
public: public:
cBlaze(); cBlaze(void);
~cBlaze();
virtual bool IsA(const char * a_EntityType) override;
virtual void GetDrops(cItems & a_Drops, cPawn * a_Killer = NULL) override;
} ;
virtual bool IsA( const char* a_EntityType );
virtual void KilledBy( cEntity* a_Killer );
};

View File

@ -7,7 +7,7 @@
cCavespider::cCavespider() cCavespider::cCavespider(void)
{ {
m_MobType = 59; m_MobType = 59;
GetMonsterConfig("Cavespider"); GetMonsterConfig("Cavespider");
@ -17,18 +17,9 @@ cCavespider::cCavespider()
cCavespider::~cCavespider() bool cCavespider::IsA(const char * a_EntityType)
{ {
} return ((strcmp(a_EntityType, "cCaveSpider") == 0) || super::IsA(a_EntityType));
bool cCavespider::IsA( const char* a_EntityType )
{
if( strcmp( a_EntityType, "cCavespider" ) == 0 ) return true;
return cMonster::IsA( a_EntityType );
} }
@ -37,7 +28,8 @@ bool cCavespider::IsA( const char* a_EntityType )
void cCavespider::Tick(float a_Dt) void cCavespider::Tick(float a_Dt)
{ {
cMonster::Tick(a_Dt); super::Tick(a_Dt);
// TODO: Check vanilla if cavespiders really get passive during the day
m_EMPersonality = (GetWorld()->GetTimeOfDay() < (12000 + 1000)) ? PASSIVE : AGGRESSIVE; m_EMPersonality = (GetWorld()->GetTimeOfDay() < (12000 + 1000)) ? PASSIVE : AGGRESSIVE;
} }
@ -45,13 +37,10 @@ void cCavespider::Tick(float a_Dt)
void cCavespider::KilledBy( cEntity* a_Killer ) void cCavespider::GetDrops(cItems & a_Drops, cPawn * a_Killer)
{ {
cItems Drops; AddRandomDropItem(a_Drops, 0, 2, E_ITEM_STRING);
AddRandomDropItem(Drops, 0, 2, E_ITEM_STRING); AddRandomDropItem(a_Drops, 0, 1, E_ITEM_SPIDER_EYE);
AddRandomDropItem(Drops, 0, 1, E_ITEM_SPIDER_EYE);
cMonster::KilledBy( a_Killer );
} }

View File

@ -1,15 +1,26 @@
#pragma once #pragma once
#include "AggressiveMonster.h" #include "AggressiveMonster.h"
class cCavespider : public cAggressiveMonster
class cCavespider :
public cAggressiveMonster
{ {
typedef cAggressiveMonster super;
public: public:
cCavespider(); cCavespider(void);
~cCavespider();
virtual bool IsA(const char * a_EntityType) override;
virtual void Tick(float a_Dt) override;
virtual void GetDrops(cItems & a_Drops, cPawn * a_Killer = NULL) override;
} ;
virtual bool IsA( const char* a_EntityType );
virtual void Tick(float a_Dt);
virtual void KilledBy( cEntity* a_Killer );
};

View File

@ -7,13 +7,13 @@
// TODO Drop egg every 5-10 minutes // TODO: Drop egg every 5-10 minutes
cChicken::cChicken() cChicken::cChicken(void)
{ {
m_MobType = 93; m_MobType = 93;
GetMonsterConfig("Chicken"); GetMonsterConfig("Chicken");
@ -23,32 +23,19 @@ cChicken::cChicken()
cChicken::~cChicken() bool cChicken::IsA(const char * a_EntityType)
{ {
return ((strcmp(a_EntityType, "cChicken") == 0) || super::IsA(a_EntityType));
} }
bool cChicken::IsA( const char* a_EntityType ) void cChicken::GetDrops(cItems & a_Drops, cPawn * a_Killer)
{ {
if( strcmp( a_EntityType, "cChicken" ) == 0 ) return true; AddRandomDropItem(a_Drops, 0, 2, E_ITEM_FEATHER);
return cMonster::IsA( a_EntityType ); a_Drops.push_back(cItem((GetMetaData() == BURNING) ? E_ITEM_COOKED_CHICKEN : E_ITEM_RAW_CHICKEN, 1));
}
void cChicken::KilledBy( cEntity* a_Killer )
{
cItems Drops;
AddRandomDropItem(Drops, 0, 2, E_ITEM_FEATHER);
Drops.push_back(cItem((GetMetaData() == BURNING) ? E_ITEM_COOKED_CHICKEN : E_ITEM_RAW_CHICKEN, 1));
m_World->SpawnItemPickups(Drops, m_Pos.x, m_Pos.y, m_Pos.z);
cMonster::KilledBy( a_Killer );
} }

View File

@ -1,14 +1,25 @@
#pragma once #pragma once
#include "PassiveMonster.h" #include "PassiveMonster.h"
class cChicken : public cPassiveMonster
class cChicken :
public cPassiveMonster
{ {
typedef cPassiveMonster super;
public: public:
cChicken(); cChicken(void);
~cChicken();
virtual bool IsA(const char * a_EntityType) override;
virtual void GetDrops(cItems & a_Drops, cPawn * a_Killer = NULL) override;
} ;
virtual bool IsA( const char* a_EntityType );
virtual void KilledBy( cEntity* a_Killer );
};

View File

@ -13,7 +13,7 @@
cCow::cCow() cCow::cCow(void)
{ {
m_MobType = 92; m_MobType = 92;
GetMonsterConfig("Cow"); GetMonsterConfig("Cow");
@ -23,32 +23,19 @@ cCow::cCow()
cCow::~cCow() bool cCow::IsA(const char * a_EntityType)
{ {
return ((strcmp(a_EntityType, "cCow") == 0) || super::IsA(a_EntityType));
} }
bool cCow::IsA( const char* a_EntityType ) void cCow::GetDrops(cItems & a_Drops, cPawn * a_Killer)
{ {
if( strcmp( a_EntityType, "cCow" ) == 0 ) return true; AddRandomDropItem(a_Drops, 0, 2, E_ITEM_LEATHER);
return cMonster::IsA( a_EntityType ); AddRandomDropItem(a_Drops, 1, 3, (GetMetaData() == BURNING) ? E_ITEM_STEAK : E_ITEM_RAW_BEEF);
}
void cCow::KilledBy( cEntity* a_Killer )
{
cItems Drops;
AddRandomDropItem(Drops, 0, 2, E_ITEM_LEATHER);
AddRandomDropItem(Drops, 1, 3, (GetMetaData() == BURNING) ? E_ITEM_STEAK : E_ITEM_RAW_BEEF);
m_World->SpawnItemPickups(Drops, m_Pos.x, m_Pos.y, m_Pos.z);
cMonster::KilledBy( a_Killer );
} }

View File

@ -1,14 +1,25 @@
#pragma once #pragma once
#include "PassiveMonster.h" #include "PassiveMonster.h"
class cCow : public cPassiveMonster
class cCow :
public cPassiveMonster
{ {
typedef cPassiveMonster super;
public: public:
cCow(); cCow();
~cCow();
virtual bool IsA( const char* a_EntityType ); virtual bool IsA(const char * a_EntityType) override;
virtual void GetDrops(cItems & a_Drops, cPawn * a_Killer = NULL) override;
} ;
virtual void KilledBy( cEntity* a_Killer );
};

View File

@ -7,7 +7,7 @@
cCreeper::cCreeper() cCreeper::cCreeper(void)
{ {
m_MobType = 50; m_MobType = 50;
GetMonsterConfig("Creeper"); GetMonsterConfig("Creeper");
@ -17,34 +17,20 @@ cCreeper::cCreeper()
cCreeper::~cCreeper() bool cCreeper::IsA(const char * a_EntityType)
{ {
return ((strcmp(a_EntityType, "cCreeper") == 0) || super::IsA(a_EntityType));
} }
bool cCreeper::IsA( const char* a_EntityType ) void cCreeper::GetDrops(cItems & a_Drops, cPawn * a_Killer)
{ {
if( strcmp( a_EntityType, "cCreeper" ) == 0 ) return true; AddRandomDropItem(a_Drops, 0, 2, E_ITEM_GUNPOWDER);
return cMonster::IsA( a_EntityType );
}
void cCreeper::KilledBy( cEntity* a_Killer )
{
cItems Drops;
AddRandomDropItem(Drops, 0, 2, E_ITEM_GUNPOWDER);
// TODO Check if killed by a skeleton, then drop random music disk // TODO Check if killed by a skeleton, then drop random music disk
m_World->SpawnItemPickups(Drops, m_Pos.x, m_Pos.y, m_Pos.z);
cMonster::KilledBy( a_Killer );
} }

View File

@ -1,14 +1,25 @@
#pragma once #pragma once
#include "AggressiveMonster.h" #include "AggressiveMonster.h"
class cCreeper : public cAggressiveMonster
class cCreeper :
public cAggressiveMonster
{ {
typedef cAggressiveMonster super;
public: public:
cCreeper(); cCreeper(void);
~cCreeper();
virtual bool IsA(const char * a_EntityType) override;
virtual void GetDrops(cItems & a_Drops, cPawn * a_Killer = NULL) override;
} ;
virtual bool IsA( const char* a_EntityType );
virtual void KilledBy( cEntity* a_Killer );
};

View File

@ -7,7 +7,7 @@
cEnderman::cEnderman() cEnderman::cEnderman(void)
{ {
m_MobType = 58; m_MobType = 58;
GetMonsterConfig("Enderman"); GetMonsterConfig("Enderman");
@ -17,18 +17,9 @@ cEnderman::cEnderman()
cEnderman::~cEnderman() bool cEnderman::IsA(const char * a_EntityType)
{ {
} return ((strcmp(a_EntityType, "cEnderman") == 0) || super::IsA(a_EntityType));
bool cEnderman::IsA( const char* a_EntityType )
{
if( strcmp( a_EntityType, "cEnderman" ) == 0 ) return true;
return cMonster::IsA( a_EntityType );
} }
@ -50,13 +41,9 @@ void cEnderman::Tick(float a_Dt)
void cEnderman::KilledBy( cEntity* a_Killer ) void cEnderman::GetDrops(cItems & a_Drops, cPawn * a_Killer)
{ {
cItems Drops; AddRandomDropItem(a_Drops, 0, 1, E_ITEM_ENDER_PEARL);
AddRandomDropItem(Drops, 0, 1, E_ITEM_ENDER_PEARL);
m_World->SpawnItemPickups(Drops, m_Pos.x, m_Pos.y, m_Pos.z);
cMonster::KilledBy( a_Killer );
} }

View File

@ -1,15 +1,26 @@
#pragma once #pragma once
#include "PassiveAggressiveMonster.h" #include "PassiveAggressiveMonster.h"
class cEnderman : public cPassiveAggressiveMonster
class cEnderman :
public cPassiveAggressiveMonster
{ {
typedef cPassiveAggressiveMonster super;
public: public:
cEnderman(); cEnderman(void);
~cEnderman();
virtual bool IsA(const char * a_EntityType) override;
virtual void Tick(float a_Dt) override;
virtual void GetDrops(cItems & a_Drops, cPawn * a_Killer = NULL) override;
} ;
virtual bool IsA( const char* a_EntityType );
virtual void Tick(float a_Dt);
virtual void KilledBy( cEntity* a_Killer );
};

View File

@ -7,7 +7,7 @@
cGhast::cGhast() cGhast::cGhast(void)
{ {
m_MobType = 56; m_MobType = 56;
GetMonsterConfig("Ghast"); GetMonsterConfig("Ghast");
@ -17,31 +17,19 @@ cGhast::cGhast()
cGhast::~cGhast() bool cGhast::IsA(const char * a_EntityType)
{ {
return ((strcmp(a_EntityType, "cGhast") == 0) || super::IsA(a_EntityType));
} }
bool cGhast::IsA( const char* a_EntityType ) void cGhast::GetDrops(cItems & a_Drops, cPawn * a_Killer)
{ {
if( strcmp( a_EntityType, "cGhast" ) == 0 ) return true; AddRandomDropItem(a_Drops, 0, 2, E_ITEM_GUNPOWDER);
return cMonster::IsA( a_EntityType ); AddRandomDropItem(a_Drops, 0, 1, E_ITEM_GHAST_TEAR);
}
void cGhast::KilledBy( cEntity* a_Killer )
{
cItems Drops;
AddRandomDropItem(Drops, 0, 2, E_ITEM_GUNPOWDER);
AddRandomDropItem(Drops, 0, 1, E_ITEM_GHAST_TEAR);
cMonster::KilledBy( a_Killer );
} }

View File

@ -1,14 +1,25 @@
#pragma once #pragma once
#include "AggressiveMonster.h" #include "AggressiveMonster.h"
class cGhast : public cAggressiveMonster
class cGhast :
public cAggressiveMonster
{ {
typedef cAggressiveMonster super;
public: public:
cGhast(); cGhast(void);
~cGhast();
virtual bool IsA(const char * a_EntityType) override;
virtual void GetDrops(cItems & a_Drops, cPawn * a_Killer = NULL) override;
} ;
virtual bool IsA( const char* a_EntityType );
virtual void KilledBy( cEntity* a_Killer );
};

View File

@ -17,31 +17,18 @@ cMagmacube::cMagmacube()
cMagmacube::~cMagmacube() bool cMagmacube::IsA(const char * a_EntityType)
{ {
return ((strcmp(a_EntityType, "cMagmacube") == 0) || super::IsA(a_EntityType));
} }
bool cMagmacube::IsA( const char* a_EntityType ) void cMagmacube::GetDrops(cItems & a_Drops, cPawn * a_Killer)
{ {
if( strcmp( a_EntityType, "cMagmacube" ) == 0 ) return true; AddRandomDropItem(a_Drops, 0, 1, E_ITEM_MAGMA_CREAM);
return cMonster::IsA( a_EntityType );
}
void cMagmacube::KilledBy( cEntity* a_Killer )
{
cItems Drops;
AddRandomDropItem(Drops, 0, 1, E_ITEM_MAGMA_CREAM);
m_World->SpawnItemPickups(Drops, m_Pos.x, m_Pos.y, m_Pos.z);
cMonster::KilledBy( a_Killer );
} }

View File

@ -1,14 +1,25 @@
#pragma once #pragma once
#include "AggressiveMonster.h" #include "AggressiveMonster.h"
class cMagmacube : public cAggressiveMonster
class cMagmacube :
public cAggressiveMonster
{ {
typedef cAggressiveMonster super;
public: public:
cMagmacube(); cMagmacube();
~cMagmacube();
virtual bool IsA( const char* a_EntityType ); virtual bool IsA(const char * a_EntityType) override;
virtual void GetDrops(cItems & a_Drops, cPawn * a_Killer = NULL) override;
} ;
virtual void KilledBy( cEntity* a_Killer );
};

View File

@ -28,8 +28,8 @@
cMonster::cMonster() cMonster::cMonster(void)
: m_Target(0) : m_Target(NULL)
, m_bMovingToDestination(false) , m_bMovingToDestination(false)
, m_DestinationTime( 0 ) , m_DestinationTime( 0 )
, m_Gravity( -9.81f) , m_Gravity( -9.81f)
@ -318,20 +318,23 @@ void cMonster::HandlePhysics(float a_Dt)
void cMonster::TakeDamage(int a_Damage, cEntity* a_Instigator) void cMonster::DoTakeDamage(TakeDamageInfo & a_TDI)
{ {
cPawn::TakeDamage( a_Damage, a_Instigator ); super::DoTakeDamage(a_TDI);
m_Target = a_Instigator; if (a_TDI.Attacker != NULL)
AddReference( m_Target ); {
m_Target = a_TDI.Attacker;
AddReference(m_Target);
}
} }
void cMonster::KilledBy( cEntity* a_Killer ) void cMonster::KilledBy(cPawn * a_Killer)
{ {
cPawn::KilledBy( a_Killer ); super::KilledBy(a_Killer);
m_DestroyTimer = 0; m_DestroyTimer = 0;
} }
@ -513,7 +516,7 @@ void cMonster::Attack(float a_Dt)
{ {
// Setting this higher gives us more wiggle room for attackrate // Setting this higher gives us more wiggle room for attackrate
m_AttackInterval = 0.0; m_AttackInterval = 0.0;
((cPawn *)m_Target)->TakeDamage((int)m_AttackDamage, this); ((cPawn *)m_Target)->TakeDamage(*this);
} }
} }

View File

@ -17,14 +17,18 @@ class cClientHandle;
class cMonster : public cPawn //tolua_export // tolua_begin
{ //tolua_export class cMonster :
public cPawn
{
typedef cPawn super;
public: public:
// tolua_end
cMonster();
cMonster(void);
virtual ~cMonster(); virtual ~cMonster();
virtual bool IsA( const char* a_EntityType ); virtual bool IsA(const char * a_EntityType);
virtual void SpawnOn(cClientHandle & a_ClientHandle) override; virtual void SpawnOn(cClientHandle & a_ClientHandle) override;
@ -33,8 +37,9 @@ public:
virtual void HandlePhysics(float a_Dt); virtual void HandlePhysics(float a_Dt);
virtual void ReplicateMovement(void); virtual void ReplicateMovement(void);
virtual void TakeDamage(int a_Damage, cEntity * a_Instigator) override; virtual void DoTakeDamage(TakeDamageInfo & a_TDI) override;
virtual void KilledBy(cEntity * a_Killer) override;
virtual void KilledBy(cPawn * a_Killer) override;
virtual void MoveToPosition(const Vector3f & a_Position); virtual void MoveToPosition(const Vector3f & a_Position);
virtual bool ReachedDestination(void); virtual bool ReachedDestination(void);
@ -47,7 +52,7 @@ public:
virtual void CheckEventSeePlayer(); virtual void CheckEventSeePlayer();
virtual void EventSeePlayer(cEntity *); virtual void EventSeePlayer(cEntity *);
float m_SightDistance; float m_SightDistance;
virtual cPlayer *FindClosestPlayer(); //non static is easier. also virtual so other mobs can implement their own searching algo virtual cPlayer * FindClosestPlayer(); // non static is easier. also virtual so other mobs can implement their own searching algo
virtual void GetMonsterConfig(const char* pm_name); virtual void GetMonsterConfig(const char* pm_name);
virtual void EventLosePlayer(); virtual void EventLosePlayer();
virtual void CheckEventLostPlayer(); virtual void CheckEventLostPlayer();
@ -69,7 +74,7 @@ public:
protected: protected:
cEntity* m_Target; cEntity * m_Target;
float m_AttackRate; float m_AttackRate;
float idle_interval; float idle_interval;
@ -94,7 +99,7 @@ protected:
float m_AttackInterval; float m_AttackInterval;
void AddRandomDropItem(cItems & a_Drops, unsigned int a_Min, unsigned int a_Max, short a_Item, short a_ItemHealth = 0); void AddRandomDropItem(cItems & a_Drops, unsigned int a_Min, unsigned int a_Max, short a_Item, short a_ItemHealth = 0);
}; //tolua_export } ; // tolua_export

View File

@ -13,7 +13,7 @@
cMooshroom::cMooshroom() cMooshroom::cMooshroom(void)
{ {
m_MobType = 96; m_MobType = 96;
GetMonsterConfig("Mooshroom"); GetMonsterConfig("Mooshroom");
@ -23,32 +23,19 @@ cMooshroom::cMooshroom()
cMooshroom::~cMooshroom() bool cMooshroom::IsA(const char * a_EntityType)
{ {
return ((strcmp(a_EntityType, "cMooshroom") == 0) || super::IsA(a_EntityType));
} }
bool cMooshroom::IsA( const char* a_EntityType ) void cMooshroom::GetDrops(cItems & a_Drops, cPawn * a_Killer)
{ {
if( strcmp( a_EntityType, "cMooshroom" ) == 0 ) return true; AddRandomDropItem(a_Drops, 0, 2, E_ITEM_LEATHER);
return cMonster::IsA( a_EntityType ); AddRandomDropItem(a_Drops, 1, 3, (GetMetaData() == BURNING) ? E_ITEM_STEAK : E_ITEM_RAW_BEEF);
}
void cMooshroom::KilledBy( cEntity* a_Killer )
{
cItems Drops;
AddRandomDropItem(Drops, 0, 2, E_ITEM_LEATHER);
AddRandomDropItem(Drops, 1, 3, (GetMetaData() == BURNING) ? E_ITEM_STEAK : E_ITEM_RAW_BEEF);
m_World->SpawnItemPickups(Drops, m_Pos.x, m_Pos.y, m_Pos.z);
cMonster::KilledBy( a_Killer );
} }

View File

@ -1,14 +1,25 @@
#pragma once #pragma once
#include "PassiveMonster.h" #include "PassiveMonster.h"
class cMooshroom : public cPassiveMonster
class cMooshroom :
public cPassiveMonster
{ {
typedef cPassiveMonster super;
public: public:
cMooshroom(); cMooshroom(void);
~cMooshroom();
virtual bool IsA(const char * a_EntityType);
virtual void GetDrops(cItems & a_Drops, cPawn * a_Killer = NULL) override;
} ;
virtual bool IsA( const char* a_EntityType );
virtual void KilledBy( cEntity* a_Killer );
};

View File

@ -17,29 +17,12 @@ cOcelot::cOcelot()
cOcelot::~cOcelot() bool cOcelot::IsA(const char * a_EntityType)
{ {
return ((strcmp(a_EntityType, "cOcelot") == 0) || super::IsA(a_EntityType));
} }
bool cOcelot::IsA( const char* a_EntityType )
{
if( strcmp( a_EntityType, "cOcelot" ) == 0 ) return true;
return cMonster::IsA( a_EntityType );
}
void cOcelot::KilledBy( cEntity* a_Killer )
{
cMonster::KilledBy( a_Killer );
}

View File

@ -1,14 +1,23 @@
#pragma once #pragma once
#include "PassiveMonster.h" #include "PassiveMonster.h"
class cOcelot : public cPassiveMonster
class cOcelot :
public cPassiveMonster
{ {
typedef cPassiveMonster super;
public: public:
cOcelot(); cOcelot();
~cOcelot();
virtual bool IsA( const char* a_EntityType ); virtual bool IsA(const char * a_EntityType) override;
} ;
virtual void KilledBy( cEntity* a_Killer );
};

View File

@ -9,30 +9,27 @@
cPassiveAggressiveMonster::cPassiveAggressiveMonster() cPassiveAggressiveMonster::cPassiveAggressiveMonster(void)
{ {
m_EMPersonality = PASSIVE; m_EMPersonality = PASSIVE;
} }
cPassiveAggressiveMonster::~cPassiveAggressiveMonster()
{
}
void cPassiveAggressiveMonster::TakeDamage(int a_Damage, cEntity* a_Instigator)
void cPassiveAggressiveMonster::DoTakeDamage(TakeDamageInfo & a_TDI)
{ {
cMonster::TakeDamage(a_Damage, a_Instigator); if ((m_Target != NULL) && (m_Target->GetEntityType() == cEntity::eEntityType_Player))
if(m_Target->GetEntityType() == cEntity::eEntityType_Player)
{ {
cPlayer * Player = (cPlayer *) m_Target; cPlayer * Player = (cPlayer *) m_Target;
if(Player->GetGameMode() != 1) if (Player->GetGameMode() != 1)
{ {
m_EMState = CHASING; m_EMState = CHASING;
} }
} }
} }
void cPassiveAggressiveMonster::EventSeePlayer(cEntity *a_Entity)
{
return cMonster::EventSeePlayer(a_Entity);
}

View File

@ -1,13 +1,23 @@
#pragma once #pragma once
#include "AggressiveMonster.h" #include "AggressiveMonster.h"
class cPassiveAggressiveMonster : public cAggressiveMonster
{
public:
cPassiveAggressiveMonster();
~cPassiveAggressiveMonster();
virtual void TakeDamage(int a_Damage, cEntity* a_Instigator);
void EventSeePlayer(cEntity *a_Entity);
};
class cPassiveAggressiveMonster :
public cAggressiveMonster
{
typedef cAggressiveMonster super;
public:
cPassiveAggressiveMonster(void);
virtual void DoTakeDamage(TakeDamageInfo & a_TDI) override;
} ;

View File

@ -8,21 +8,27 @@
cPassiveMonster::cPassiveMonster() cPassiveMonster::cPassiveMonster(void)
{ {
m_EMPersonality = PASSIVE; m_EMPersonality = PASSIVE;
} }
cPassiveMonster::~cPassiveMonster()
void cPassiveMonster::DoTakeDamage(TakeDamageInfo & a_TDI)
{ {
super::DoTakeDamage(a_TDI);
if ((a_TDI.Attacker != this) && (a_TDI.Attacker != NULL))
{
m_EMState = ESCAPING;
}
} }
void cPassiveMonster::TakeDamage(int a_Damage, cEntity* a_Instigator)
{
cMonster::TakeDamage(a_Damage, a_Instigator);
if(a_Instigator != this)
m_EMState = ESCAPING;
}
void cPassiveMonster::Tick(float a_Dt) void cPassiveMonster::Tick(float a_Dt)
{ {
@ -30,17 +36,22 @@ void cPassiveMonster::Tick(float a_Dt)
m_SeePlayerInterval += a_Dt; m_SeePlayerInterval += a_Dt;
if(m_SeePlayerInterval > 1) if (m_SeePlayerInterval > 1) // Check every second
{ {
MTRand r1; MTRand r1;
int rem = r1.randInt() % 3 + 1; //check most of the time but miss occasionally int rem = r1.randInt() % 3 + 1; // Check most of the time but miss occasionally
m_SeePlayerInterval = 0.0; m_SeePlayerInterval = 0.0;
if(rem >= 2) { if (rem >= 2)
if(m_EMState == ESCAPING) {
if (m_EMState == ESCAPING)
{ {
CheckEventLostPlayer(); CheckEventLostPlayer();
} }
} }
} }
} }

View File

@ -1,14 +1,26 @@
#pragma once #pragma once
#include "Monster.h" #include "Monster.h"
class cPassiveMonster : public cMonster
class cPassiveMonster :
public cMonster
{ {
typedef cMonster super;
public: public:
cPassiveMonster(); cPassiveMonster(void);
~cPassiveMonster();
virtual void Tick(float a_Dt) override;
/// When hit by someone, run away
virtual void DoTakeDamage(TakeDamageInfo & a_TDI) override;
} ;
virtual void Tick(float a_Dt);
virtual void TakeDamage(int a_Damage, cEntity* a_Instigator);
};

View File

@ -7,7 +7,7 @@
cPig::cPig() cPig::cPig(void)
{ {
m_MobType = 90; m_MobType = 90;
GetMonsterConfig("Pig"); GetMonsterConfig("Pig");
@ -17,33 +17,18 @@ cPig::cPig()
cPig::~cPig() bool cPig::IsA(const char * a_EntityType)
{ {
return ((strcmp(a_EntityType, "cPig") == 0) || super::IsA(a_EntityType));
} }
bool cPig::IsA( const char* a_EntityType ) void cPig::GetDrops(cItems & a_Drops, cPawn * a_Killer)
{ {
if( strcmp( a_EntityType, "cPig" ) == 0 ) return true; AddRandomDropItem(a_Drops, 1, 3, (GetMetaData() == BURNING) ? E_ITEM_COOKED_PORKCHOP : E_ITEM_RAW_MEAT);
return cMonster::IsA( a_EntityType );
}
void cPig::KilledBy( cEntity* a_Killer )
{
cItems Drops;
AddRandomDropItem(Drops, 0, 2, E_ITEM_RAW_MEAT);
m_World->SpawnItemPickups(Drops, m_Pos.x, m_Pos.y, m_Pos.z);
// TODO: Check for burning state
cMonster::KilledBy( a_Killer );
} }

View File

@ -1,14 +1,25 @@
#pragma once #pragma once
#include "PassiveMonster.h" #include "PassiveMonster.h"
class cPig : public cPassiveMonster
class cPig :
public cPassiveMonster
{ {
typedef cPassiveMonster super;
public: public:
cPig(); cPig(void);
~cPig();
virtual bool IsA(const char * a_EntityType) override;
virtual void GetDrops(cItems & a_Drops, cPawn * a_Killer = NULL) override;
} ;
virtual bool IsA( const char* a_EntityType );
virtual void KilledBy( cEntity* a_Killer );
};

View File

@ -2,12 +2,7 @@
#include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules #include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules
#include "Sheep.h" #include "Sheep.h"
#include "../BlockID.h"
//Todo: Implement color
@ -15,7 +10,7 @@
cSheep::cSheep(void) : cSheep::cSheep(void) :
m_IsSheared(false), m_IsSheared(false),
m_WoolColor(0) // TODO: E_META_WOOL_WHITE m_WoolColor(E_META_WOOL_WHITE)
{ {
m_MobType = 91; m_MobType = 91;
GetMonsterConfig("Sheep"); GetMonsterConfig("Sheep");
@ -25,41 +20,23 @@ cSheep::cSheep(void) :
cSheep::~cSheep() bool cSheep::IsA(const char * a_EntityType)
{ {
return ((strcmp(a_EntityType, "cSheep") == 0) || super::IsA(a_EntityType));
} }
bool cSheep::IsA( const char* a_EntityType ) void cSheep::GetDrops(cItems & a_Drops, cPawn * a_Killer)
{ {
if (strcmp( a_EntityType, "cSheep" ) == 0)
{
return true;
}
return cMonster::IsA( a_EntityType );
}
void cSheep::KilledBy( cEntity* a_Killer )
{
// TODO: Check whether it is sheared
// TODO: Check color
if (!m_IsSheared) if (!m_IsSheared)
{ {
cItems Drops; a_Drops.push_back(cItem(E_ITEM_WHITE_CLOTH, 1, m_WoolColor));
Drops.push_back(cItem(E_ITEM_WHITE_CLOTH, 1, m_WoolColor));
m_World->SpawnItemPickups(Drops, m_Pos.x, m_Pos.y, m_Pos.z);
} }
cMonster::KilledBy( a_Killer );
} }

View File

@ -1,17 +1,28 @@
#pragma once #pragma once
#include "PassiveMonster.h" #include "PassiveMonster.h"
class cSheep : public cPassiveMonster
class cSheep :
public cPassiveMonster
{ {
typedef cPassiveMonster super;
public: public:
cSheep(); cSheep(void);
~cSheep();
bool m_IsSheared; bool m_IsSheared;
NIBBLETYPE m_WoolColor; // Uses E_META_WOOL_ constants for colors NIBBLETYPE m_WoolColor; // Uses E_META_WOOL_ constants for colors
virtual bool IsA(const char * a_EntityType); virtual bool IsA(const char * a_EntityType) override;
virtual void GetDrops(cItems & a_Drops, cPawn * a_Killer = NULL) override;
} ;
virtual void KilledBy(cEntity * a_Killer);
};

View File

@ -8,5 +8,5 @@ public:
cSilverfish(); cSilverfish();
~cSilverfish(); ~cSilverfish();
virtual bool IsA( const char* a_EntityType ); virtual bool IsA(const char * a_EntityType);
}; };

View File

@ -7,7 +7,7 @@
cSkeleton::cSkeleton() cSkeleton::cSkeleton(void)
{ {
m_MobType = 51; m_MobType = 51;
GetMonsterConfig("Skeleton"); GetMonsterConfig("Skeleton");
@ -17,18 +17,9 @@ cSkeleton::cSkeleton()
cSkeleton::~cSkeleton()
{
}
bool cSkeleton::IsA( const char* a_EntityType ) bool cSkeleton::IsA( const char* a_EntityType )
{ {
if( strcmp( a_EntityType, "cSkeleton" ) == 0 ) return true; return ((strcmp(a_EntityType, "cSkeleton") == 0) || super::IsA(a_EntityType));
return cMonster::IsA( a_EntityType );
} }
@ -51,14 +42,10 @@ void cSkeleton::Tick(float a_Dt)
void cSkeleton::KilledBy( cEntity* a_Killer ) void cSkeleton::GetDrops(cItems & a_Drops, cPawn * a_Killer)
{ {
cItems Drops; AddRandomDropItem(a_Drops, 0, 2, E_ITEM_ARROW);
AddRandomDropItem(Drops, 0, 2, E_ITEM_ARROW); AddRandomDropItem(a_Drops, 0, 2, E_ITEM_BONE);
AddRandomDropItem(Drops, 0, 2, E_ITEM_BONE);
m_World->SpawnItemPickups(Drops, m_Pos.x, m_Pos.y, m_Pos.z);
cMonster::KilledBy( a_Killer );
} }

View File

@ -1,16 +1,26 @@
#pragma once #pragma once
#include "AggressiveMonster.h" #include "AggressiveMonster.h"
class cSkeleton : public cAggressiveMonster
class cSkeleton :
public cAggressiveMonster
{ {
typedef cAggressiveMonster super;
public: public:
cSkeleton(); cSkeleton();
~cSkeleton();
virtual bool IsA( const char* a_EntityType ); virtual bool IsA(const char * a_EntityType) override;
virtual void Tick(float a_Dt) override;
virtual void GetDrops(cItems & a_Drops, cPawn * a_Killer = NULL) override;
} ;
virtual void Tick(float a_Dt);
virtual void KilledBy( cEntity* a_Killer );
};

View File

@ -3,13 +3,13 @@
#include "Slime.h" #include "Slime.h"
//TODO Implement sized slimes // TODO: Implement sized slimes
cSlime::cSlime() cSlime::cSlime(void)
{ {
m_MobType = 55; m_MobType = 55;
GetMonsterConfig("Slime"); GetMonsterConfig("Slime");
@ -19,32 +19,19 @@ cSlime::cSlime()
cSlime::~cSlime() bool cSlime::IsA(const char * a_EntityType)
{ {
return ((strcmp(a_EntityType, "cSlime") == 0) || super::IsA(a_EntityType));
} }
bool cSlime::IsA( const char* a_EntityType ) void cSlime::GetDrops(cItems & a_Drops, cPawn * a_Killer)
{ {
if( strcmp( a_EntityType, "cSlime" ) == 0 ) return true; // TODO: only when tiny
return cMonster::IsA( a_EntityType ); AddRandomDropItem(a_Drops, 0, 2, E_ITEM_SLIMEBALL);
}
void cSlime::KilledBy( cEntity* a_Killer )
{
//TODO: only when tiny
cItems Drops;
AddRandomDropItem(Drops, 0, 2, E_ITEM_SLIMEBALL);
m_World->SpawnItemPickups(Drops, m_Pos.x, m_Pos.y, m_Pos.z);
cMonster::KilledBy( a_Killer );
} }

View File

@ -1,14 +1,21 @@
#pragma once #pragma once
#include "AggressiveMonster.h" #include "AggressiveMonster.h"
class cSlime : public cAggressiveMonster class cSlime :
public cAggressiveMonster
{ {
typedef cAggressiveMonster super;
public: public:
cSlime(); cSlime();
~cSlime();
virtual bool IsA( const char* a_EntityType ); virtual bool IsA(const char * a_EntityType) override;
virtual void GetDrops(cItems & a_Drops, cPawn * a_Killer = NULL) override;
} ;
virtual void KilledBy( cEntity* a_Killer );
};

View File

@ -17,32 +17,19 @@ cSpider::cSpider()
cSpider::~cSpider() bool cSpider::IsA(const char * a_EntityType)
{ {
return ((strcmp(a_EntityType, "cSpider") == 0) || super::IsA(a_EntityType));
} }
bool cSpider::IsA( const char* a_EntityType ) void cSpider::GetDrops(cItems & a_Drops, cPawn * a_Killer)
{ {
if( strcmp( a_EntityType, "cSpider" ) == 0 ) return true; AddRandomDropItem(a_Drops, 0, 2, E_ITEM_STRING);
return cMonster::IsA( a_EntityType ); AddRandomDropItem(a_Drops, 0, 1, E_ITEM_SPIDER_EYE);
}
void cSpider::KilledBy( cEntity* a_Killer )
{
cItems Drops;
AddRandomDropItem(Drops, 0, 2, E_ITEM_STRING);
AddRandomDropItem(Drops, 0, 1, E_ITEM_SPIDER_EYE);
m_World->SpawnItemPickups(Drops, m_Pos.x, m_Pos.y, m_Pos.z);
cMonster::KilledBy( a_Killer );
} }

View File

@ -1,14 +1,25 @@
#pragma once #pragma once
#include "AggressiveMonster.h" #include "AggressiveMonster.h"
class cSpider : public cAggressiveMonster
class cSpider :
public cAggressiveMonster
{ {
typedef cAggressiveMonster super;
public: public:
cSpider(); cSpider();
~cSpider();
virtual bool IsA( const char* a_EntityType ); virtual bool IsA(const char * a_EntityType) override;
virtual void GetDrops(cItems & a_Drops, cPawn * a_Killer = NULL) override;
} ;
virtual void KilledBy( cEntity* a_Killer );
};

View File

@ -12,32 +12,25 @@ cSquid::cSquid()
{ {
m_MobType = 94; m_MobType = 94;
GetMonsterConfig("Squid"); GetMonsterConfig("Squid");
m_NoWater = 0.f;
} }
cSquid::~cSquid()
bool cSquid::IsA(const char * a_EntityType)
{ {
return ((strcmp(a_EntityType, "cSquid") == 0) || super::IsA(a_EntityType));
}
bool cSquid::IsA( const char* a_EntityType )
{
if( strcmp( a_EntityType, "cSquid" ) == 0 ) return true;
return cMonster::IsA( a_EntityType );
} }
void cSquid::KilledBy( cEntity* a_Killer ) void cSquid::GetDrops(cItems & a_Drops, cPawn * a_Killer)
{ {
// Drops 0-3 Ink Sacs // Drops 0-3 Ink Sacs
cItems Drops; AddRandomDropItem(a_Drops, 0, 3, E_ITEM_DYE, E_META_DYE_BLACK);
AddRandomDropItem(Drops, 0, 3, E_ITEM_DYE, E_META_DYE_BLACK);
m_World->SpawnItemPickups(Drops, m_Pos.x, m_Pos.y, m_Pos.z);
cMonster::KilledBy( a_Killer );
} }
@ -46,15 +39,17 @@ void cSquid::KilledBy( cEntity* a_Killer )
void cSquid::Tick(float a_Dt) void cSquid::Tick(float a_Dt)
{ {
cPassiveMonster::Tick(a_Dt); super::Tick(a_Dt);
Vector3d Pos = GetPosition(); Vector3d Pos = GetPosition();
// TODO: Not a real behavior, but cool :D
//TODO Not a real behavior, but cool :D if (!IsBlockWater(GetWorld()->GetBlock((int) Pos.x, (int) Pos.y, (int) Pos.z)) && GetMetaData() != BURNING)
if(!IsBlockWater(GetWorld()->GetBlock((int) Pos.x, (int) Pos.y, (int) Pos.z)) && GetMetaData() != BURNING)
{ {
SetMetaData(BURNING); SetMetaData(BURNING);
} }
}
}

View File

@ -1,18 +1,26 @@
#pragma once #pragma once
#include "PassiveMonster.h" #include "PassiveMonster.h"
class cSquid : public cPassiveMonster
class cSquid :
public cPassiveMonster
{ {
typedef cPassiveMonster super;
public: public:
cSquid(); cSquid();
~cSquid();
virtual void Tick(float a_Dt); virtual void Tick(float a_Dt) override;
virtual bool IsA(const char * a_EntityType) override;
virtual void GetDrops(cItems & a_Drops, cPawn * a_Killer = NULL) override;
} ;
virtual bool IsA( const char* a_EntityType );
virtual void KilledBy( cEntity* a_Killer );
protected:
float m_NoWater;
};

View File

@ -17,27 +17,9 @@ cVillager::cVillager()
cVillager::~cVillager() bool cVillager::IsA(const char * a_EntityType)
{ {
} return ((strcmp(a_EntityType, "cVillager") == 0) || super::IsA(a_EntityType));
bool cVillager::IsA( const char* a_EntityType )
{
if( strcmp( a_EntityType, "cVillager" ) == 0 ) return true;
return cMonster::IsA( a_EntityType );
}
void cVillager::KilledBy( cEntity* a_Killer )
{
cMonster::KilledBy( a_Killer );
} }

View File

@ -1,14 +1,23 @@
#pragma once #pragma once
#include "PassiveMonster.h" #include "PassiveMonster.h"
class cVillager : public cPassiveMonster
class cVillager :
public cPassiveMonster
{ {
typedef cPassiveMonster super;
public: public:
cVillager(); cVillager();
~cVillager();
virtual bool IsA( const char* a_EntityType ); virtual bool IsA(const char * a_EntityType) override;
} ;
virtual void KilledBy( cEntity* a_Killer );
};

View File

@ -17,37 +17,24 @@ cWitch::cWitch()
cWitch::~cWitch() bool cWitch::IsA(const char * a_EntityType)
{ {
return ((strcmp(a_EntityType, "cWitch") == 0) || super::IsA(a_EntityType));
} }
bool cWitch::IsA( const char* a_EntityType ) void cWitch::GetDrops(cItems & a_Drops, cPawn * a_Killer)
{ {
if( strcmp( a_EntityType, "cWitch" ) == 0 ) return true; AddRandomDropItem(a_Drops, 0, 6, E_ITEM_GLASS_BOTTLE);
return cMonster::IsA( a_EntityType ); AddRandomDropItem(a_Drops, 0, 6, E_ITEM_GLOWSTONE_DUST);
} AddRandomDropItem(a_Drops, 0, 6, E_ITEM_GUNPOWDER);
AddRandomDropItem(a_Drops, 0, 6, E_ITEM_REDSTONE_DUST);
AddRandomDropItem(a_Drops, 0, 6, E_ITEM_SPIDER_EYE);
AddRandomDropItem(a_Drops, 0, 6, E_ITEM_STICK);
AddRandomDropItem(a_Drops, 0, 6, E_ITEM_SUGAR);
void cWitch::KilledBy( cEntity* a_Killer )
{
cItems Drops;
AddRandomDropItem(Drops, 0, 6, E_ITEM_GLASS_BOTTLE);
AddRandomDropItem(Drops, 0, 6, E_ITEM_GLOWSTONE_DUST);
AddRandomDropItem(Drops, 0, 6, E_ITEM_GUNPOWDER);
AddRandomDropItem(Drops, 0, 6, E_ITEM_REDSTONE_DUST);
AddRandomDropItem(Drops, 0, 6, E_ITEM_SPIDER_EYE);
AddRandomDropItem(Drops, 0, 6, E_ITEM_STICK);
AddRandomDropItem(Drops, 0, 6, E_ITEM_SUGAR);
m_World->SpawnItemPickups(Drops, m_Pos.x, m_Pos.y, m_Pos.z);
cMonster::KilledBy( a_Killer );
} }

View File

@ -1,14 +1,25 @@
#pragma once #pragma once
#include "AggressiveMonster.h" #include "AggressiveMonster.h"
class cWitch : public cAggressiveMonster
class cWitch :
public cAggressiveMonster
{ {
typedef cAggressiveMonster super;
public: public:
cWitch(); cWitch();
~cWitch();
virtual bool IsA( const char* a_EntityType ); virtual bool IsA(const char* a_EntityType) override;
virtual void GetDrops(cItems & a_Drops, cPawn * a_Killer = NULL) override;
} ;
virtual void KilledBy( cEntity* a_Killer );
};

View File

@ -17,18 +17,9 @@ cZombie::cZombie()
cZombie::~cZombie() bool cZombie::IsA(const char * a_EntityType)
{ {
} return ((strcmp(a_EntityType, "cZombie") == 0) || super::IsA(a_EntityType));
bool cZombie::IsA( const char* a_EntityType )
{
if( strcmp( a_EntityType, "cZombie" ) == 0 ) return true;
return cMonster::IsA( a_EntityType );
} }
@ -37,7 +28,7 @@ bool cZombie::IsA( const char* a_EntityType )
void cZombie::Tick(float a_Dt) void cZombie::Tick(float a_Dt)
{ {
cMonster::Tick(a_Dt); super::Tick(a_Dt);
// TODO Same as in cSkeleton :D // TODO Same as in cSkeleton :D
if ((GetWorld()->GetTimeOfDay() < (12000 + 1000)) && (GetMetaData() != BURNING)) if ((GetWorld()->GetTimeOfDay() < (12000 + 1000)) && (GetMetaData() != BURNING))
@ -50,16 +41,11 @@ void cZombie::Tick(float a_Dt)
void cZombie::KilledBy( cEntity* a_Killer ) void cZombie::GetDrops(cItems & a_Drops, cPawn * a_Killer)
{ {
cItems Drops; AddRandomDropItem(a_Drops, 0, 2, E_ITEM_ROTTEN_FLESH);
AddRandomDropItem(Drops, 0, 2, E_ITEM_ROTTEN_FLESH);
// TODO: Rare drops // TODO: Rare drops
m_World->SpawnItemPickups(Drops, m_Pos.x, m_Pos.y, m_Pos.z);
cMonster::KilledBy( a_Killer );
} }

View File

@ -2,14 +2,24 @@
#include "AggressiveMonster.h" #include "AggressiveMonster.h"
class cZombie : public cAggressiveMonster
class cZombie :
public cAggressiveMonster
{ {
typedef cAggressiveMonster super;
public: public:
cZombie(); cZombie();
~cZombie();
virtual bool IsA( const char* a_EntityType ); virtual bool IsA(const char * a_EntityType) override;
virtual void Tick(float a_Dt) override;
virtual void GetDrops(cItems & a_Drops, cPawn * a_Killer = NULL) override;
} ;
virtual void Tick(float a_Dt);
virtual void KilledBy( cEntity* a_Killer );
};

View File

@ -17,18 +17,9 @@ cZombiepigman::cZombiepigman()
cZombiepigman::~cZombiepigman() bool cZombiepigman::IsA(const char * a_EntityType)
{ {
} return ((strcmp(a_EntityType, "cZombiepigman") == 0) || super::IsA(a_EntityType));
bool cZombiepigman::IsA( const char* a_EntityType )
{
if( strcmp( a_EntityType, "cZombiepigman" ) == 0 ) return true;
return cMonster::IsA( a_EntityType );
} }
@ -37,7 +28,7 @@ bool cZombiepigman::IsA( const char* a_EntityType )
void cZombiepigman::Tick(float a_Dt) void cZombiepigman::Tick(float a_Dt)
{ {
cMonster::Tick(a_Dt); super::Tick(a_Dt);
// TODO Same as noticed in cSkeleton AND Do they really burn by sun?? :D In the neather is no sun :D // TODO Same as noticed in cSkeleton AND Do they really burn by sun?? :D In the neather is no sun :D
if ((GetWorld()->GetTimeOfDay() < (12000 + 1000)) && (GetMetaData() != BURNING)) if ((GetWorld()->GetTimeOfDay() < (12000 + 1000)) && (GetMetaData() != BURNING))
@ -50,17 +41,27 @@ void cZombiepigman::Tick(float a_Dt)
void cZombiepigman::KilledBy(cEntity * a_Killer) void cZombiepigman::GetDrops(cItems & a_Drops, cPawn * a_Killer)
{ {
cItems Drops; AddRandomDropItem(a_Drops, 0, 1, E_ITEM_ROTTEN_FLESH);
AddRandomDropItem(Drops, 0, 1, E_ITEM_ROTTEN_FLESH); AddRandomDropItem(a_Drops, 0, 1, E_ITEM_GOLD_NUGGET);
AddRandomDropItem(Drops, 0, 1, E_ITEM_GOLD_NUGGET);
// TODO: Rare drops // TODO: Rare drops
}
m_World->SpawnItemPickups(Drops, m_Pos.x, m_Pos.y, m_Pos.z);
cMonster::KilledBy( a_Killer );
void cZombiepigman::KilledBy(cPawn * a_Killer)
{
super::KilledBy(a_Killer);
if ((a_Killer != NULL) && (a_Killer->GetEntityType() == eEntityType_Player))
{
// TODO: Anger all nearby zombie pigmen
// TODO: In vanilla, if one player angers ZPs, do they attack any nearby player, or only that one attacker?
}
} }

View File

@ -1,15 +1,27 @@
#pragma once #pragma once
#include "PassiveAggressiveMonster.h" #include "PassiveAggressiveMonster.h"
class cZombiepigman : public cPassiveAggressiveMonster
class cZombiepigman :
public cPassiveAggressiveMonster
{ {
typedef cPassiveAggressiveMonster super;
public: public:
cZombiepigman(); cZombiepigman();
~cZombiepigman();
virtual bool IsA( const char* a_EntityType ); virtual bool IsA(const char * a_EntityType) override;
virtual void Tick(float a_Dt) override;
virtual void GetDrops(cItems & a_Drops, cPawn * a_Killer = NULL) override;
virtual void KilledBy(cPawn * a_Killer) override;
} ;
virtual void Tick(float a_Dt);
virtual void KilledBy( cEntity* a_Killer );
};

View File

@ -21,8 +21,10 @@ CLASS_DEFINITION( cPawn, cEntity )
cPawn::cPawn() cPawn::cPawn(void)
: cEntity( 0, 0, 0 ) : cEntity( 0, 0, 0 )
, m_Health(1)
, m_MaxHealth(1)
, m_LastPosX( 0.0 ) , m_LastPosX( 0.0 )
, m_LastPosY( 0.0 ) , m_LastPosY( 0.0 )
, m_LastPosZ( 0.0 ) , m_LastPosZ( 0.0 )
@ -30,7 +32,6 @@ cPawn::cPawn()
, m_bBurnable(true) , m_bBurnable(true)
, m_MetaData(NORMAL) , m_MetaData(NORMAL)
{ {
SetMaxHealth(20);
} }
@ -39,40 +40,83 @@ cPawn::cPawn()
cPawn::~cPawn() cPawn::~cPawn()
{ {
// Nothing needed yet
} }
void cPawn::Heal( int a_Health ) void cPawn::Heal(int a_HitPoints)
{ {
(void)a_Health; m_Health += a_HitPoints;
if (m_Health > m_MaxHealth)
{
m_Health = m_MaxHealth;
}
} }
void cPawn::TakeDamage(int a_Damage, cEntity * a_Instigator) void cPawn::TakeDamage(cPawn & a_Attacker)
{
int RawDamage = a_Attacker.GetRawDamageAgainst(*this);
TakeDamage(dtAttack, &a_Attacker, RawDamage, a_Attacker.GetKnockbackAmountAgainst(*this));
}
void cPawn::TakeDamage(eDamageType a_DamageType, cPawn * a_Attacker, int a_RawDamage, double a_KnockbackAmount)
{
int FinalDamage = a_RawDamage - GetArmorCoverAgainst(a_Attacker, a_DamageType, a_RawDamage);
TakeDamage(a_DamageType, a_Attacker, a_RawDamage, FinalDamage, a_KnockbackAmount);
}
void cPawn::TakeDamage(eDamageType a_DamageType, cPawn * a_Attacker, int a_RawDamage, int a_FinalDamage, double a_KnockbackAmount)
{ {
TakeDamageInfo TDI; TakeDamageInfo TDI;
TDI.Damage = a_Damage; TDI.DamageType = a_DamageType;
TDI.Instigator = a_Instigator; TDI.Attacker = a_Attacker;
cRoot::Get()->GetPluginManager()->CallHook( cPluginManager::E_PLUGIN_TAKE_DAMAGE, 2, this, &TDI); TDI.RawDamage = a_RawDamage;
TDI.FinalDamage = a_FinalDamage;
Vector3d Heading;
Heading.x = sin(m_Rot.x);
Heading.y = 0.4; // TODO: adjust the amount of "up" knockback when testing
Heading.z = cos(m_Rot.x);
TDI.Knockback = Heading * a_KnockbackAmount;
DoTakeDamage(TDI);
}
if (TDI.Damage == 0)
void cPawn::DoTakeDamage(TakeDamageInfo & a_TDI)
{
if (cRoot::Get()->GetPluginManager()->CallHookTakeDamage(*this, a_TDI))
{ {
return; return;
} }
if (m_Health <= 0) if (m_Health <= 0)
{ {
// Can't take damage if already dead // Can't take damage if already dead
return; return;
} }
m_Health -= (short)TDI.Damage; m_Health -= (short)a_TDI.FinalDamage;
// TODO: Apply damage to armor
if (m_Health < 0) if (m_Health < 0)
{ {
m_Health = 0; m_Health = 0;
@ -82,7 +126,7 @@ void cPawn::TakeDamage(int a_Damage, cEntity * a_Instigator)
if (m_Health <= 0) if (m_Health <= 0)
{ {
KilledBy(TDI.Instigator); KilledBy(a_TDI.Attacker);
} }
} }
@ -90,15 +134,23 @@ void cPawn::TakeDamage(int a_Damage, cEntity * a_Instigator)
void cPawn::KilledBy(cEntity * a_Killer) void cPawn::KilledBy(cPawn * a_Killer)
{ {
short OldHealth = m_Health;
m_Health = 0; m_Health = 0;
if( cRoot::Get()->GetPluginManager()->CallHook( cPluginManager::E_PLUGIN_KILLED, 2, this, a_Killer ) ) if (cRoot::Get()->GetPluginManager()->CallHook( cPluginManager::E_PLUGIN_KILLED, 2, this, a_Killer))
{ {
return; // Give plugins a chance to 'unkill' the pawn. // Plugin wants to 'unkill' the pawn. Set health back and abort
m_Health = OldHealth;
return;
} }
// Drop loot:
cItems Drops;
GetDrops(Drops, a_Killer);
m_World->SpawnItemPickups(Drops, m_Pos.x, m_Pos.y, m_Pos.z);
m_World->BroadcastEntityStatus(*this, ENTITY_STATUS_DEAD); m_World->BroadcastEntityStatus(*this, ENTITY_STATUS_DEAD);
} }
@ -106,18 +158,147 @@ void cPawn::KilledBy(cEntity * a_Killer)
void cPawn::TeleportToEntity(cEntity * a_Entity) int cPawn::GetRawDamageAgainst(const cPawn & a_Receiver)
{ {
TeleportTo(a_Entity->GetPosX(), a_Entity->GetPosY(), a_Entity->GetPosZ()); // Returns the hitpoints that this pawn can deal to a_Receiver using its equipped items
// Ref: http://www.minecraftwiki.net/wiki/Damage#Dealing_damage as of 2012_12_20
switch (this->GetEquippedWeapon().m_ItemType)
{
case E_ITEM_WOODEN_SWORD: return 4;
case E_ITEM_GOLD_SWORD: return 4;
case E_ITEM_STONE_SWORD: return 5;
case E_ITEM_IRON_SWORD: return 6;
case E_ITEM_DIAMOND_SWORD: return 7;
case E_ITEM_WOODEN_AXE: return 3;
case E_ITEM_GOLD_AXE: return 3;
case E_ITEM_STONE_AXE: return 4;
case E_ITEM_IRON_AXE: return 5;
case E_ITEM_DIAMOND_AXE: return 6;
case E_ITEM_WOODEN_PICKAXE: return 2;
case E_ITEM_GOLD_PICKAXE: return 2;
case E_ITEM_STONE_PICKAXE: return 3;
case E_ITEM_IRON_PICKAXE: return 4;
case E_ITEM_DIAMOND_PICKAXE: return 5;
case E_ITEM_WOODEN_SHOVEL: return 1;
case E_ITEM_GOLD_SHOVEL: return 1;
case E_ITEM_STONE_SHOVEL: return 2;
case E_ITEM_IRON_SHOVEL: return 3;
case E_ITEM_DIAMOND_SHOVEL: return 4;
}
// All other equipped items give a damage of 1:
return 1;
} }
void cPawn::TeleportTo( const double & a_PosX, const double & a_PosY, const double & a_PosZ ) int cPawn::GetArmorCoverAgainst(const cPawn * a_Attacker, eDamageType a_DamageType, int a_Damage)
{ {
SetPosition( a_PosX, a_PosY, a_PosZ ); // Returns the hitpoints out of a_RawDamage that the currently equipped armor would cover
// Filter out damage types that are not protected by armor:
// Ref.: http://www.minecraftwiki.net/wiki/Armor#Effects as of 2012_12_20
switch (a_DamageType)
{
case dtOnFire:
case dtSuffocating:
case dtDrowning: // TODO: This one could be a special case - in various MC versions (PC vs XBox) it is and isn't armor-protected
case dtStarving:
case dtInVoid:
case dtPoisoning:
case dtPotionOfHarming:
case dtFalling:
case dtLightning:
{
return 0;
}
}
// Add up all armor points:
// Ref.: http://www.minecraftwiki.net/wiki/Armor#Defense_points as of 2012_12_20
int ArmorValue = 0;
switch (GetEquippedHelmet().m_ItemType)
{
case E_ITEM_LEATHER_CAP: ArmorValue += 1; break;
case E_ITEM_GOLD_HELMET: ArmorValue += 2; break;
case E_ITEM_CHAIN_HELMET: ArmorValue += 2; break;
case E_ITEM_IRON_HELMET: ArmorValue += 2; break;
case E_ITEM_DIAMOND_HELMET: ArmorValue += 3; break;
}
switch (GetEquippedChestplate().m_ItemType)
{
case E_ITEM_LEATHER_TUNIC: ArmorValue += 3; break;
case E_ITEM_GOLD_CHESTPLATE: ArmorValue += 5; break;
case E_ITEM_CHAIN_CHESTPLATE: ArmorValue += 5; break;
case E_ITEM_IRON_CHESTPLATE: ArmorValue += 6; break;
case E_ITEM_DIAMOND_CHESTPLATE: ArmorValue += 8; break;
}
switch (GetEquippedLeggings().m_ItemType)
{
case E_ITEM_LEATHER_PANTS: ArmorValue += 2; break;
case E_ITEM_GOLD_LEGGINGS: ArmorValue += 3; break;
case E_ITEM_CHAIN_LEGGINGS: ArmorValue += 4; break;
case E_ITEM_IRON_LEGGINGS: ArmorValue += 5; break;
case E_ITEM_DIAMOND_LEGGINGS: ArmorValue += 6; break;
}
switch (GetEquippedBoots().m_ItemType)
{
case E_ITEM_LEATHER_BOOTS: ArmorValue += 1; break;
case E_ITEM_GOLD_BOOTS: ArmorValue += 1; break;
case E_ITEM_CHAIN_BOOTS: ArmorValue += 1; break;
case E_ITEM_IRON_BOOTS: ArmorValue += 2; break;
case E_ITEM_DIAMOND_BOOTS: ArmorValue += 3; break;
}
// TODO: Special armor cases, such as wool, saddles, dog's collar
// Ref.: http://www.minecraftwiki.net/wiki/Armor#Mob_armor as of 2012_12_20
// Now ArmorValue is in [0, 20] range, which corresponds to [0, 80%] protection. Calculate the hitpoints from that:
return a_Damage * (ArmorValue * 4) / 100;
}
double cPawn::GetKnockbackAmountAgainst(const cPawn & a_Receiver)
{
// Returns the knockback amount that the currently equipped items would cause to a_Receiver on a hit
// TODO: Enchantments
return 1;
}
void cPawn::GetDrops(cItems & a_Drops, cPawn * a_Killer)
{
UNUSED(a_Drops);
UNUSED(a_Killer);
}
void cPawn::TeleportToEntity(cEntity & a_Entity)
{
TeleportTo(a_Entity.GetPosX(), a_Entity.GetPosY(), a_Entity.GetPosZ());
}
void cPawn::TeleportTo(double a_PosX, double a_PosY, double a_PosZ)
{
SetPosition(a_PosX, a_PosY, a_PosZ);
GetWorld()->BroadcastTeleportEntity(*this); GetWorld()->BroadcastTeleportEntity(*this);
} }
@ -155,9 +336,9 @@ void cPawn::SetMetaData(MetaData a_MetaData)
//----Change Entity MetaData //----Change Entity MetaData
void cPawn::CheckMetaDataBurn() void cPawn::CheckMetaDataBurn()
{ {
char Block = GetWorld()->GetBlock((int) m_Pos.x, (int) m_Pos.y, (int) m_Pos.z); BLOCKTYPE Block = GetWorld()->GetBlock((int) m_Pos.x, (int) m_Pos.y, (int) m_Pos.z);
char BlockAbove = GetWorld()->GetBlock((int) m_Pos.x, (int) m_Pos.y + 1, (int) m_Pos.z); BLOCKTYPE BlockAbove = GetWorld()->GetBlock((int) m_Pos.x, (int) m_Pos.y + 1, (int) m_Pos.z);
char BlockBelow = GetWorld()->GetBlock((int) m_Pos.x, (int) m_Pos.y - 1, (int) m_Pos.z); BLOCKTYPE BlockBelow = GetWorld()->GetBlock((int) m_Pos.x, (int) m_Pos.y - 1, (int) m_Pos.z);
if ( if (
(GetMetaData() == BURNING) && (GetMetaData() == BURNING) &&
@ -184,35 +365,36 @@ void cPawn::CheckMetaDataBurn()
//What to do if On fire // What to do if On fire
void cPawn::InStateBurning(float a_Dt) void cPawn::InStateBurning(float a_Dt)
{ {
m_FireDamageInterval += a_Dt; m_FireDamageInterval += a_Dt;
char Block = GetWorld()->GetBlock( (int)m_Pos.x, (int)m_Pos.y, (int)m_Pos.z ); if (m_FireDamageInterval < 800)
char BlockAbove = GetWorld()->GetBlock( (int)m_Pos.x, (int)m_Pos.y + 1, (int)m_Pos.z );
if (m_FireDamageInterval > 800)
{ {
return;
}
m_FireDamageInterval = 0; BLOCKTYPE Block = GetWorld()->GetBlock((int)m_Pos.x, (int)m_Pos.y, (int)m_Pos.z);
TakeDamage(1, this); BLOCKTYPE BlockAbove = GetWorld()->GetBlock((int)m_Pos.x, (int)m_Pos.y + 1, (int)m_Pos.z);
m_FireDamageInterval = 0;
TakeDamage(dtOnFire, NULL, 1, 0);
m_BurnPeriod++; m_BurnPeriod++;
if (IsBlockLava(Block) || Block == E_BLOCK_FIRE if (
|| IsBlockLava(BlockAbove) || BlockAbove == E_BLOCK_FIRE) IsBlockLava(Block) ||
{ (Block == E_BLOCK_FIRE) ||
m_BurnPeriod = 0; IsBlockLava(BlockAbove) ||
TakeDamage(6, this); (BlockAbove == E_BLOCK_FIRE)
} )
else {
{ m_BurnPeriod = 0;
TakeDamage(1, this); TakeDamage(dtLavaContact, NULL, 6, 0);
} }
if (m_BurnPeriod > 7) if (m_BurnPeriod > 7)
{ {
SetMetaData(NORMAL); SetMetaData(NORMAL);
m_BurnPeriod = 0; m_BurnPeriod = 0;
}
} }
} }
@ -224,7 +406,7 @@ void cPawn::SetMaxHealth(short a_MaxHealth)
{ {
this->m_MaxHealth = a_MaxHealth; this->m_MaxHealth = a_MaxHealth;
//Reset health // Reset health
m_Health = a_MaxHealth; m_Health = a_MaxHealth;
} }

View File

@ -2,38 +2,145 @@
#pragma once #pragma once
#include "Entity.h" #include "Entity.h"
#include "Item.h"
struct TakeDamageInfo //tolua_export // fwd:
{ //tolua_export class cPawn;
int Damage; //tolua_export
cEntity* Instigator; //tolua_export
}; //tolua_export
class cPawn : public cEntity //tolua_export // tolua_begin
{ //tolua_export enum eDamageType
{
// Canonical names for the types (as documented in the plugin wiki):
dtAttack, // Being attacked by a mob
dtLightning, // Hit by a lightning strike
dtFalling, // Falling down; dealt when hitting the ground
dtDrowning, // Drowning in water / lava
dtSuffocating, // Suffocating inside a block
dtStarving, // Hunger
dtCactusContact, // Contact with a cactus block
dtLavaContact, // Contact with a lava block
dtPoisoning, // Having the poison effect
dtOnFire, // Being on fire
dtFireContact, // Standing inside a fire block
dtInVoid, // Falling into the Void (Y < 0)
dtPotionOfHarming,
// Some common synonyms:
dtPawnAttack = dtAttack,
dtEntityAttack = dtAttack,
dtMob = dtAttack,
dtMobAttack = dtAttack,
dtFall = dtFalling,
dtDrown = dtDrowning,
dtSuffocation = dtSuffocating,
dtStarvation = dtStarving,
dtHunger = dtStarving,
dtCactus = dtCactusContact,
dtCactuses = dtCactusContact,
dtCacti = dtCactusContact,
dtLava = dtLavaContact,
dtPoison = dtPoisoning,
dtBurning = dtOnFire,
dtInFire = dtFireContact,
} ;
struct TakeDamageInfo
{
eDamageType DamageType; // Where does the damage come from? Being hit / on fire / contact with cactus / ...
cPawn * Attacker; // The attacking pawn; 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 cPawn :
public cEntity
{
// tolua_end
public: public:
CLASS_PROTOTYPE() CLASS_PROTOTYPE()
cPawn(); cPawn(void);
virtual ~cPawn(); virtual ~cPawn();
virtual void TeleportToEntity( cEntity* a_Entity ); //tolua_export
virtual void TeleportTo( const double & a_PosX, const double & a_PosY, const double & a_PosZ ); //tolua_export
virtual void Tick(float a_Dt) override; virtual void Tick(float a_Dt) override;
void Heal( int a_Health ); //tolua_export // tolua_begin
virtual void TakeDamage( int a_Damage, cEntity* a_Instigator ); //tolua_export
virtual void KilledBy( cEntity* a_Killer ); //tolua_export /// Teleports to the entity specified
int GetHealth() { return m_Health; } //tolua_export virtual void TeleportToEntity(cEntity & a_Entity);
/// Teleports to the coordinates specified
virtual void TeleportTo(double a_PosX, double a_PosY, double a_PosZ);
/// Heals the specified amount of HPs
void Heal(int a_HitPoints);
/// Returns the health of this pawn
int GetHealth(void) const { return m_Health; }
/// Makes this pawn take damage from an attack by a_Attacker. Damage values are calculated automatically and DoTakeDamage() called
void TakeDamage(cPawn & a_Attacker);
/// Makes this pawn take the specified damage. The final damage is calculated using current armor, then DoTakeDamage() called
void TakeDamage(eDamageType a_DamageType, cPawn * a_Attacker, int a_RawDamage, double a_KnockbackAmount);
/// Makes this pawn take the specified damage. The values are packed into a TDI, knockback calculated, then sent through DoTakeDamage()
void TakeDamage(eDamageType a_DamageType, cPawn * a_Attacker, int a_RawDamage, int a_FinalDamage, double a_KnockbackAmount);
/// Makes this pawn take damage specified in the a_TDI. The TDI is sent through plugins first, then applied
virtual void DoTakeDamage(TakeDamageInfo & a_TDI);
/// Called when the health drops below zero. a_Killer may be NULL (environmental damage)
virtual void KilledBy(cPawn * a_Killer);
/// Returns the hitpoints that this pawn can deal to a_Receiver using its equipped items
virtual int GetRawDamageAgainst(const cPawn & a_Receiver);
/// Returns the hitpoints out of a_RawDamage that the currently equipped armor would cover
virtual int GetArmorCoverAgainst(const cPawn * 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 cPawn & 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 nonte
virtual cItem GetEquippedHelmet(void) const { return cItem(); }
/// Returns the currently equipped chestplate; empty item if nonte
virtual cItem GetEquippedChestplate(void) const { return cItem(); }
/// Returns the currently equipped leggings; empty item if nonte
virtual cItem GetEquippedLeggings(void) const { return cItem(); }
/// Returns the currently equipped boots; empty item if nonte
virtual cItem GetEquippedBoots(void) const { return cItem(); }
// tolua_end
/// 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, cPawn * a_Killer = NULL);
enum MetaData {NORMAL, BURNING, CROUCHED, RIDING, SPRINTING, EATING, BLOCKING}; enum MetaData {NORMAL, BURNING, CROUCHED, RIDING, SPRINTING, EATING, BLOCKING};
@ -48,10 +155,8 @@ public:
virtual short GetMaxHealth() { return m_MaxHealth; } virtual short GetMaxHealth() { return m_MaxHealth; }
protected: protected:
short m_Health; short m_Health;
short m_MaxHealth; short m_MaxHealth;
bool m_bBurnable; bool m_bBurnable;

View File

@ -70,6 +70,7 @@ cPlayer::cPlayer(cClientHandle* a_Client, const AString & a_PlayerName)
LOGD("Inventory window for player %p is at %p", this, m_InventoryWindow); LOGD("Inventory window for player %p is at %p", this, m_InventoryWindow);
SetMaxHealth(20); SetMaxHealth(20);
m_MaxFoodLevel = 20; m_MaxFoodLevel = 20;
m_MaxFoodSaturationLevel = 20.f; m_MaxFoodSaturationLevel = 20.f;
@ -222,18 +223,19 @@ void cPlayer::Tick(float a_Dt)
{ {
m_World->CollectPickupsByPlayer(this); m_World->CollectPickupsByPlayer(this);
//Handle Health: // Handle Health:
m_FoodTickTimer++; m_FoodTickTimer++;
if(m_FoodTickTimer >= 80) if (m_FoodTickTimer >= 80)
{ {
m_FoodTickTimer = 0; m_FoodTickTimer = 0;
if(m_FoodLevel >= 17) if (m_FoodLevel >= 17)
{ {
Heal(1); Heal(1);
}else if(m_FoodLevel == 0) }
else if (m_FoodLevel == 0)
{ {
TakeDamage(1, NULL); super::TakeDamage(dtStarving, NULL, 1, 1, 0);
} }
} }
@ -248,7 +250,7 @@ void cPlayer::Tick(float a_Dt)
} }
else else
{ {
m_FoodLevel = MAX(m_FoodLevel -1, 0); m_FoodLevel = MAX(m_FoodLevel - 1, 0);
} }
SendHealth(); SendHealth();
@ -297,7 +299,7 @@ void cPlayer::SetTouchGround(bool a_bTouchGround)
m_LastJumpHeight = (float)m_Pos.y; m_LastJumpHeight = (float)m_Pos.y;
if (Damage > 0) if (Damage > 0)
{ {
TakeDamage(Damage, 0); super::TakeDamage(dtFalling, NULL, Damage, Damage, 0);
} }
m_LastGroundHeight = (float)m_Pos.y; m_LastGroundHeight = (float)m_Pos.y;
@ -353,23 +355,30 @@ void cPlayer::SendHealth()
void cPlayer::TakeDamage( int a_Damage, cEntity* a_Instigator ) void cPlayer::DoTakeDamage(TakeDamageInfo & a_TDI)
{ {
if (m_GameMode != eGameMode_Creative) if (m_GameMode == eGameMode_Creative)
{ {
cPawn::TakeDamage( a_Damage, a_Instigator ); // No damage / health in creative mode
return;
AddFoodExhaustion(0.3f);
SendHealth();
} }
super::DoTakeDamage(a_TDI);
if (a_TDI.Attacker != NULL)
{
// Only increase hunger if being attacked by a mob
AddFoodExhaustion(0.3f);
}
SendHealth();
} }
void cPlayer::KilledBy(cEntity * a_Killer) void cPlayer::KilledBy(cPawn * a_Killer)
{ {
cPawn::KilledBy(a_Killer); cPawn::KilledBy(a_Killer);
@ -544,7 +553,7 @@ void cPlayer::SendMessage(const AString & a_Message)
void cPlayer::TeleportTo(const double & a_PosX, const double & a_PosY, const double & a_PosZ) void cPlayer::TeleportTo(double a_PosX, double a_PosY, double a_PosZ)
{ {
SetPosition( a_PosX, a_PosY, a_PosZ ); SetPosition( a_PosX, a_PosY, a_PosZ );

View File

@ -17,9 +17,17 @@ class cClientHandle;
class cPlayer : public cPawn //tolua_export // tolua_begin
{ //tolua_export class cPlayer :
public cPawn
{
public: public:
enum
{
MAX_HEALTH = 20,
} ;
// tolua_end
typedef cPawn super; typedef cPawn super;
CLASS_PROTOTYPE() CLASS_PROTOTYPE()
@ -33,6 +41,21 @@ public:
virtual void Tick(float a_Dt) override; virtual void Tick(float a_Dt) override;
/// Returns the curently equipped weapon; empty item if none
virtual cItem GetEquippedWeapon(void) const override { return m_Inventory.GetEquippedItem(); }
/// Returns the currently equipped helmet; empty item if nonte
virtual cItem GetEquippedHelmet(void) const override { return m_Inventory.GetEquippedHelmet(); }
/// Returns the currently equipped chestplate; empty item if none
virtual cItem GetEquippedChestplate(void) const override { return m_Inventory.GetEquippedChestplate(); }
/// Returns the currently equipped leggings; empty item if none
virtual cItem GetEquippedLeggings(void) const override { return m_Inventory.GetEquippedLeggings(); }
/// Returns the currently equipped boots; empty item if none
virtual cItem GetEquippedBoots(void) const override { return m_Inventory.GetEquippedBoots(); }
void SetTouchGround( bool a_bTouchGround ); void SetTouchGround( bool a_bTouchGround );
inline void SetStance( const double a_Stance ) { m_Stance = a_Stance; } inline void SetStance( const double a_Stance ) { m_Stance = a_Stance; }
double GetEyeHeight(); //tolua_export double GetEyeHeight(); //tolua_export
@ -44,7 +67,7 @@ public:
inline const cItem & GetEquippedItem(void) const {return GetInventory().GetEquippedItem(); } // tolua_export inline const cItem & GetEquippedItem(void) const {return GetInventory().GetEquippedItem(); } // tolua_export
virtual void TeleportTo( const double & a_PosX, const double & a_PosY, const double & a_PosZ ); //tolua_export virtual void TeleportTo(double a_PosX, double a_PosY, double a_PosZ) override;
eGameMode GetGameMode(void) const { return m_GameMode; } //tolua_export eGameMode GetGameMode(void) const { return m_GameMode; } //tolua_export
std::string GetIP() { return m_IP; } //tolua_export std::string GetIP() { return m_IP; } //tolua_export
@ -100,18 +123,18 @@ public:
void AddFoodExhaustion(float a_Exhaustion) { m_FoodExhaustionLevel += a_Exhaustion; } //tolua_export void AddFoodExhaustion(float a_Exhaustion) { m_FoodExhaustionLevel += a_Exhaustion; } //tolua_export
void TakeDamage( int a_Damage, cEntity* a_Instigator ); //tolua_export virtual void KilledBy(cPawn * a_Killer) override;
void KilledBy( cEntity* a_Killer ); //tolua_export
void Respawn(); //tolua_export void Respawn(void); //tolua_export
void SetVisible( bool a_bVisible ); //tolua_export void SetVisible( bool a_bVisible ); //tolua_export
bool IsVisible() { return m_bVisible; } //tolua_export bool IsVisible(void) const { return m_bVisible; } //tolua_export
bool MoveToWorld( const char* a_WorldName ); //tolua_export bool MoveToWorld(const char * a_WorldName ); //tolua_export
bool SaveToDisk(); bool SaveToDisk(void);
bool LoadFromDisk(); bool LoadFromDisk(void);
void LoadPermissionsFromDisk(); //tolua_export void LoadPermissionsFromDisk(void); //tolua_export
const AString & GetLoadedWorldName() { return m_LoadedWorldName; } const AString & GetLoadedWorldName() { return m_LoadedWorldName; }
@ -171,4 +194,12 @@ protected:
static const unsigned short PLAYER_LIST_TIME_MS = 1000; // 1000 = once per second static const unsigned short PLAYER_LIST_TIME_MS = 1000; // 1000 = once per second
cClientHandle* m_ClientHandle; cClientHandle* m_ClientHandle;
}; //tolua_export
/// Filters out damage for creative mode
virtual void DoTakeDamage(TakeDamageInfo & TDI) override;
} ; //tolua_export

View File

@ -2,6 +2,7 @@
#include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules #include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules
#include "Plugin.h" #include "Plugin.h"
#include "Pawn.h"
@ -228,10 +229,11 @@ bool cPlugin::OnPreCrafting(const cPlayer * a_Player, const cCraftingGrid * a_Gr
void cPlugin::OnTakeDamage(cPawn * a_Pawn, TakeDamageInfo * a_TakeDamageInfo) bool cPlugin::OnTakeDamage(cPawn & a_Pawn, TakeDamageInfo & a_TakeDamageInfo)
{ {
UNUSED(a_Pawn); UNUSED(a_Pawn);
UNUSED(a_TakeDamageInfo); UNUSED(a_TakeDamageInfo);
return false;
} }

View File

@ -57,7 +57,7 @@ public:
virtual void OnPlayerSpawn (cPlayer* a_Player ); virtual void OnPlayerSpawn (cPlayer* a_Player );
virtual bool OnPostCrafting (const cPlayer * a_Player, const cCraftingGrid * a_Grid, cCraftingRecipe * a_Recipe); virtual bool OnPostCrafting (const cPlayer * a_Player, const cCraftingGrid * a_Grid, cCraftingRecipe * a_Recipe);
virtual bool OnPreCrafting (const cPlayer * a_Player, const cCraftingGrid * a_Grid, cCraftingRecipe * a_Recipe); virtual bool OnPreCrafting (const cPlayer * a_Player, const cCraftingGrid * a_Grid, cCraftingRecipe * a_Recipe);
virtual void OnTakeDamage (cPawn * a_Pawn, TakeDamageInfo * a_TakeDamageInfo ); virtual bool OnTakeDamage (cPawn & a_Receiver, TakeDamageInfo & a_TakeDamageInfo);
virtual bool OnUpdatedSign (cWorld * a_World, int a_BlockX, int a_BlockY, int a_BlockZ, const AString & a_Line1, const AString & a_Line2, const AString & a_Line3, const AString & a_Line4, cPlayer * a_Player); virtual bool OnUpdatedSign (cWorld * a_World, int a_BlockX, int a_BlockY, int a_BlockZ, const AString & a_Line1, const AString & a_Line2, const AString & a_Line3, const AString & a_Line4, cPlayer * a_Player);
virtual bool OnUpdatingSign (cWorld * a_World, int a_BlockX, int a_BlockY, int a_BlockZ, AString & a_Line1, AString & a_Line2, AString & a_Line3, AString & a_Line4, cPlayer * a_Player); virtual bool OnUpdatingSign (cWorld * a_World, int a_BlockX, int a_BlockY, int a_BlockZ, AString & a_Line1, AString & a_Line2, AString & a_Line3, AString & a_Line4, cPlayer * a_Player);
virtual bool OnWeatherChanged (cWorld * a_World); virtual bool OnWeatherChanged (cWorld * a_World);

View File

@ -253,21 +253,6 @@ bool cPluginManager::CallHook(PluginHook a_Hook, unsigned int a_NumArgs, ...)
break; break;
} }
case HOOK_TAKE_DAMAGE:
{
if( a_NumArgs != 2 ) break;
va_list argptr;
va_start( argptr, a_NumArgs);
cPawn* Pawn = va_arg(argptr, cPawn* );
TakeDamageInfo* TDI = va_arg(argptr, TakeDamageInfo* );
va_end (argptr);
for( PluginList::iterator itr = Plugins->second.begin(); itr != Plugins->second.end(); ++itr )
{
(*itr)->OnTakeDamage( Pawn, TDI );
}
break;
}
case HOOK_KILLED: case HOOK_KILLED:
{ {
if( a_NumArgs != 2 ) break; if( a_NumArgs != 2 ) break;
@ -482,27 +467,6 @@ bool cPluginManager::CallHookCollectPickup(cPlayer * a_Player, cPickup & a_Picku
bool cPluginManager::CallHookPreCrafting(const cPlayer * a_Player, const cCraftingGrid * a_Grid, cCraftingRecipe * a_Recipe)
{
HookMap::iterator Plugins = m_Hooks.find(HOOK_PRE_CRAFTING);
if (Plugins == m_Hooks.end())
{
return false;
}
for (PluginList::iterator itr = Plugins->second.begin(); itr != Plugins->second.end(); ++itr)
{
if ((*itr)->OnPreCrafting(a_Player, a_Grid, a_Recipe))
{
return true;
}
}
return false;
}
bool cPluginManager::CallHookCraftingNoRecipe(const cPlayer * a_Player, const cCraftingGrid * a_Grid, cCraftingRecipe * a_Recipe) bool cPluginManager::CallHookCraftingNoRecipe(const cPlayer * a_Player, const cCraftingGrid * a_Grid, cCraftingRecipe * a_Recipe)
{ {
HookMap::iterator Plugins = m_Hooks.find(HOOK_CRAFTING_NO_RECIPE); HookMap::iterator Plugins = m_Hooks.find(HOOK_CRAFTING_NO_RECIPE);
@ -566,6 +530,48 @@ bool cPluginManager::CallHookPostCrafting(const cPlayer * a_Player, const cCraft
bool cPluginManager::CallHookPreCrafting(const cPlayer * a_Player, const cCraftingGrid * a_Grid, cCraftingRecipe * a_Recipe)
{
HookMap::iterator Plugins = m_Hooks.find(HOOK_PRE_CRAFTING);
if (Plugins == m_Hooks.end())
{
return false;
}
for (PluginList::iterator itr = Plugins->second.begin(); itr != Plugins->second.end(); ++itr)
{
if ((*itr)->OnPreCrafting(a_Player, a_Grid, a_Recipe))
{
return true;
}
}
return false;
}
bool cPluginManager::CallHookTakeDamage(cPawn & a_Receiver, TakeDamageInfo & a_TDI)
{
HookMap::iterator Plugins = m_Hooks.find(HOOK_TAKE_DAMAGE);
if (Plugins == m_Hooks.end())
{
return false;
}
for (PluginList::iterator itr = Plugins->second.begin(); itr != Plugins->second.end(); ++itr)
{
if ((*itr)->OnTakeDamage(a_Receiver, a_TDI))
{
return true;
}
}
return false;
}
bool cPluginManager::CallHookBlockToPickup( bool cPluginManager::CallHookBlockToPickup(
BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta,
const cPlayer * a_Player, const cItem & a_EquippedItem, cItems & a_Pickups const cPlayer * a_Player, const cItem & a_EquippedItem, cItems & a_Pickups

View File

@ -12,22 +12,26 @@ class cLuaCommandBinder;
class cPlugin; class cPlugin;
// fwd: cWorld.h // fwd: World.h
class cWorld; class cWorld;
// fwd: cLuaChunk.h // fwd: LuaChunk.h
class cLuaChunk; class cLuaChunk;
// fwd: cPlayer.h // fwd: Player.h
class cPlayer; class cPlayer;
// fwd: CraftingRecipes.h // fwd: CraftingRecipes.h
class cCraftingGrid; class cCraftingGrid;
class cCraftingRecipe; class cCraftingRecipe;
// fwd: cPickup.h // fwd: Pickup.h
class cPickup; class cPickup;
// fwd: Pawn.h
struct TakeDamageInfo;
class cPawn;
@ -54,7 +58,7 @@ public: //tolua_export
HOOK_PLAYER_SPAWN, HOOK_PLAYER_SPAWN,
HOOK_PLAYER_JOIN, HOOK_PLAYER_JOIN,
HOOK_PLAYER_MOVE, HOOK_PLAYER_MOVE,
HOOK_TAKE_DAMAGE, HOOK_TAKE_DAMAGE, // cPawn, TakeDamageInfo
HOOK_KILLED, HOOK_KILLED,
HOOK_CHUNK_GENERATED, HOOK_CHUNK_GENERATED,
HOOK_CHUNK_GENERATING, HOOK_CHUNK_GENERATING,
@ -115,6 +119,7 @@ public: //tolua_export
bool CallHookLogin (cClientHandle * a_Client, int a_ProtocolVersion, const AString & a_Username); bool CallHookLogin (cClientHandle * a_Client, int a_ProtocolVersion, const AString & a_Username);
bool CallHookPostCrafting (const cPlayer * a_Player, const cCraftingGrid * a_Grid, cCraftingRecipe * a_Recipe); bool CallHookPostCrafting (const cPlayer * a_Player, const cCraftingGrid * a_Grid, cCraftingRecipe * a_Recipe);
bool CallHookPreCrafting (const cPlayer * a_Player, const cCraftingGrid * a_Grid, cCraftingRecipe * a_Recipe); bool CallHookPreCrafting (const cPlayer * a_Player, const cCraftingGrid * a_Grid, cCraftingRecipe * a_Recipe);
bool CallHookTakeDamage (cPawn & a_Receiver, TakeDamageInfo & a_TDI);
bool CallHookUpdatedSign (cWorld * a_World, int a_BlockX, int a_BlockY, int a_BlockZ, const AString & a_Line1, const AString & a_Line2, const AString & a_Line3, const AString & a_Line4, cPlayer * a_Player); bool CallHookUpdatedSign (cWorld * a_World, int a_BlockX, int a_BlockY, int a_BlockZ, const AString & a_Line1, const AString & a_Line2, const AString & a_Line3, const AString & a_Line4, cPlayer * a_Player);
bool CallHookUpdatingSign (cWorld * a_World, int a_BlockX, int a_BlockY, int a_BlockZ, AString & a_Line1, AString & a_Line2, AString & a_Line3, AString & a_Line4, cPlayer * a_Player); bool CallHookUpdatingSign (cWorld * a_World, int a_BlockX, int a_BlockY, int a_BlockZ, AString & a_Line1, AString & a_Line2, AString & a_Line3, AString & a_Line4, cPlayer * a_Player);
bool CallHookWeatherChanged (cWorld * a_World); bool CallHookWeatherChanged (cWorld * a_World);

View File

@ -366,16 +366,25 @@ void cPlugin_NewLua::OnPlayerMove( cPlayer* a_Player )
void cPlugin_NewLua::OnTakeDamage( cPawn* a_Pawn, TakeDamageInfo* a_TakeDamageInfo ) bool cPlugin_NewLua::OnTakeDamage(cPawn & a_Receiver, TakeDamageInfo & a_TDI)
{ {
cCSLock Lock( m_CriticalSection ); cCSLock Lock(m_CriticalSection);
if( !PushFunction("OnTakeDamage") ) if (!PushFunction("OnTakeDamage"))
return; {
return false;
}
tolua_pushusertype(m_LuaState, a_Pawn, "cPawn"); tolua_pushusertype(m_LuaState, &a_Receiver, "cPawn");
tolua_pushusertype(m_LuaState, a_TakeDamageInfo, "TakeDamageInfo"); tolua_pushusertype(m_LuaState, &a_TDI, "TakeDamageInfo");
CallFunction(2, 0, "OnTakeDamage"); if (!CallFunction(2, 1, "OnTakeDamage"))
{
return false;
}
bool bRetVal = (tolua_toboolean(m_LuaState, -1, 0) != 0);
lua_pop(m_LuaState, 1);
return bRetVal;
} }

View File

@ -14,9 +14,14 @@ typedef struct lua_State lua_State;
class cPlugin_NewLua : public cPlugin, public cWebPlugin //tolua_export // tolua_begin
{ //tolua_export class cPlugin_NewLua :
public: //tolua_export public cPlugin,
public cWebPlugin
{
public:
// tolua_end
cPlugin_NewLua( const AString & a_PluginDirectory ); cPlugin_NewLua( const AString & a_PluginDirectory );
~cPlugin_NewLua(); ~cPlugin_NewLua();
@ -41,7 +46,7 @@ public: //tolua_export
virtual void OnPlayerSpawn (cPlayer * a_Player ) override; virtual void OnPlayerSpawn (cPlayer * a_Player ) override;
virtual bool OnPostCrafting (const cPlayer * a_Player, const cCraftingGrid * a_Grid, cCraftingRecipe * a_Recipe) override; virtual bool OnPostCrafting (const cPlayer * a_Player, const cCraftingGrid * a_Grid, cCraftingRecipe * a_Recipe) override;
virtual bool OnPreCrafting (const cPlayer * a_Player, const cCraftingGrid * a_Grid, cCraftingRecipe * a_Recipe) override; virtual bool OnPreCrafting (const cPlayer * a_Player, const cCraftingGrid * a_Grid, cCraftingRecipe * a_Recipe) override;
virtual void OnTakeDamage (cPawn * a_Pawn, TakeDamageInfo * a_TakeDamageInfo ) override; virtual bool OnTakeDamage (cPawn & a_Receiver, TakeDamageInfo & a_TakeDamageInfo) override;
virtual bool OnUpdatedSign (cWorld * a_World, int a_BlockX, int a_BlockY, int a_BlockZ, const AString & a_Line1, const AString & a_Line2, const AString & a_Line3, const AString & a_Line4, cPlayer * a_Player) override; virtual bool OnUpdatedSign (cWorld * a_World, int a_BlockX, int a_BlockY, int a_BlockZ, const AString & a_Line1, const AString & a_Line2, const AString & a_Line3, const AString & a_Line4, cPlayer * a_Player) override;
virtual bool OnUpdatingSign (cWorld * a_World, int a_BlockX, int a_BlockY, int a_BlockZ, AString & a_Line1, AString & a_Line2, AString & a_Line3, AString & a_Line4, cPlayer * a_Player) override; virtual bool OnUpdatingSign (cWorld * a_World, int a_BlockX, int a_BlockY, int a_BlockZ, AString & a_Line1, AString & a_Line2, AString & a_Line3, AString & a_Line4, cPlayer * a_Player) override;
virtual bool OnWeatherChanged (cWorld * a_World) override; virtual bool OnWeatherChanged (cWorld * a_World) override;