diff options
Diffstat (limited to 'src/Mobs')
-rw-r--r-- | src/Mobs/AggressiveMonster.cpp | 2 | ||||
-rw-r--r-- | src/Mobs/AggressiveMonster.h | 2 | ||||
-rw-r--r-- | src/Mobs/CMakeLists.txt | 1 | ||||
-rw-r--r-- | src/Mobs/Enderman.cpp | 169 | ||||
-rw-r--r-- | src/Mobs/Enderman.h | 7 | ||||
-rw-r--r-- | src/Mobs/Monster.cpp | 209 | ||||
-rw-r--r-- | src/Mobs/Monster.h | 78 | ||||
-rw-r--r-- | src/Mobs/MonsterTypes.h | 54 | ||||
-rw-r--r-- | src/Mobs/Mooshroom.cpp | 2 | ||||
-rw-r--r-- | src/Mobs/PassiveAggressiveMonster.cpp | 2 | ||||
-rw-r--r-- | src/Mobs/PassiveAggressiveMonster.h | 2 | ||||
-rw-r--r-- | src/Mobs/PassiveMonster.cpp | 2 | ||||
-rw-r--r-- | src/Mobs/PassiveMonster.h | 2 | ||||
-rw-r--r-- | src/Mobs/Sheep.cpp | 9 | ||||
-rw-r--r-- | src/Mobs/Villager.cpp | 6 | ||||
-rw-r--r-- | src/Mobs/Villager.h | 2 | ||||
-rw-r--r-- | src/Mobs/Wolf.cpp | 6 | ||||
-rw-r--r-- | src/Mobs/Wolf.h | 10 |
18 files changed, 442 insertions, 123 deletions
diff --git a/src/Mobs/AggressiveMonster.cpp b/src/Mobs/AggressiveMonster.cpp index 5f5b1853d..be2f71f7a 100644 --- a/src/Mobs/AggressiveMonster.cpp +++ b/src/Mobs/AggressiveMonster.cpp @@ -11,7 +11,7 @@ -cAggressiveMonster::cAggressiveMonster(const AString & a_ConfigName, eType a_MobType, const AString & a_SoundHurt, const AString & a_SoundDeath, double a_Width, double a_Height) : +cAggressiveMonster::cAggressiveMonster(const AString & a_ConfigName, eMonsterType a_MobType, const AString & a_SoundHurt, const AString & a_SoundDeath, double a_Width, double a_Height) : super(a_ConfigName, a_MobType, a_SoundHurt, a_SoundDeath, a_Width, a_Height) { m_EMPersonality = AGGRESSIVE; diff --git a/src/Mobs/AggressiveMonster.h b/src/Mobs/AggressiveMonster.h index d70ff04a3..2549ba2d3 100644 --- a/src/Mobs/AggressiveMonster.h +++ b/src/Mobs/AggressiveMonster.h @@ -14,7 +14,7 @@ class cAggressiveMonster : public: - cAggressiveMonster(const AString & a_ConfigName, eType a_MobType, const AString & a_SoundHurt, const AString & a_SoundDeath, double a_Width, double a_Height); + cAggressiveMonster(const AString & a_ConfigName, eMonsterType a_MobType, const AString & a_SoundHurt, const AString & a_SoundDeath, double a_Width, double a_Height); virtual void Tick (float a_Dt, cChunk & a_Chunk) override; virtual void InStateChasing(float a_Dt) override; diff --git a/src/Mobs/CMakeLists.txt b/src/Mobs/CMakeLists.txt index 2c092c15f..bbbb9287a 100644 --- a/src/Mobs/CMakeLists.txt +++ b/src/Mobs/CMakeLists.txt @@ -54,6 +54,7 @@ SET (HDRS IronGolem.h MagmaCube.h Monster.h + MonsterTypes.h Mooshroom.h Ocelot.h PassiveAggressiveMonster.h diff --git a/src/Mobs/Enderman.cpp b/src/Mobs/Enderman.cpp index becc99a86..567714382 100644 --- a/src/Mobs/Enderman.cpp +++ b/src/Mobs/Enderman.cpp @@ -2,6 +2,76 @@ #include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules #include "Enderman.h" +#include "../Entities/Player.h" +#include "../Tracer.h" + + + + +//////////////////////////////////////////////////////////////////////////////// +// cPlayerLookCheck +class cPlayerLookCheck : + public cPlayerListCallback +{ +public: + cPlayerLookCheck(Vector3d a_EndermanPos, int a_SightDistance) : + m_Player(NULL), + m_EndermanPos(a_EndermanPos), + m_SightDistance(a_SightDistance) + { + } + + virtual bool Item(cPlayer * a_Player) override + { + // Don't check players who are in creative gamemode + if (a_Player->IsGameModeCreative()) + { + return false; + } + + Vector3d Direction = m_EndermanPos - a_Player->GetPosition(); + + // Don't check players who are more then SightDistance (64) blocks away + if (Direction.Length() > m_SightDistance) + { + return false; + } + + // Don't check if the player has a pumpkin on his head + if (a_Player->GetEquippedHelmet().m_ItemType == E_BLOCK_PUMPKIN) + { + return false; + } + + + Vector3d LookVector = a_Player->GetLookVector(); + double dot = Direction.Dot(LookVector); + + // 0.09 rad ~ 5 degrees + // If the player's crosshair is within 5 degrees of the enderman, it counts as looking + if (dot <= cos(0.09)) + { + return false; + } + + cTracer LineOfSight(a_Player->GetWorld()); + if (LineOfSight.Trace(m_EndermanPos, Direction, (int)Direction.Length())) + { + // No direct line of sight + return false; + } + + m_Player = a_Player; + return true; + } + + cPlayer * GetPlayer(void) const { return m_Player; } + +protected: + cPlayer * m_Player; + Vector3d m_EndermanPos; + int m_SightDistance; +} ; @@ -32,3 +102,102 @@ void cEnderman::GetDrops(cItems & a_Drops, cEntity * a_Killer) +void cEnderman::CheckEventSeePlayer() +{ + if (m_Target != NULL) + { + return; + } + + cPlayerLookCheck Callback(GetPosition(), m_SightDistance); + if (m_World->ForEachPlayer(Callback)) + { + return; + } + + ASSERT(Callback.GetPlayer() != NULL); + + if (!CheckLight()) + { + // Insufficient light for enderman to become aggravated + // TODO: Teleport to a suitable location + return; + } + + if (!Callback.GetPlayer()->IsGameModeCreative()) + { + super::EventSeePlayer(Callback.GetPlayer()); + m_EMState = CHASING; + m_bIsScreaming = true; + GetWorld()->BroadcastEntityMetadata(*this); + } +} + + + + + +void cEnderman::CheckEventLostPlayer(void) +{ + super::CheckEventLostPlayer(); + if (!CheckLight()) + { + EventLosePlayer(); + } +} + + + + + +void cEnderman::EventLosePlayer() +{ + super::EventLosePlayer(); + m_bIsScreaming = false; + GetWorld()->BroadcastEntityMetadata(*this); +} + + + + + +bool cEnderman::CheckLight() +{ + int ChunkX, ChunkZ; + cChunkDef::BlockToChunk(POSX_TOINT, POSZ_TOINT, ChunkX, ChunkZ); + + // Check if the chunk the enderman is in is lit + if (!m_World->IsChunkLighted(ChunkX, ChunkZ)) + { + m_World->QueueLightChunk(ChunkX, ChunkZ); + return true; + } + + // Enderman only attack if the skylight is lower or equal to 8 + if (m_World->GetBlockSkyLight(POSX_TOINT, POSY_TOINT, POSZ_TOINT) - GetWorld()->GetSkyDarkness() > 8) + { + return false; + } + + return true; +} + + + + + +void cEnderman::Tick(float a_Dt, cChunk & a_Chunk) +{ + super::Tick(a_Dt, a_Chunk); + + // TODO take damage in rain + + // Take damage when touching water, drowning damage seems to be most appropriate + if (IsSwimming()) + { + EventLosePlayer(); + TakeDamage(dtDrowning, NULL, 1, 0); + // TODO teleport to a safe location + } + +} diff --git a/src/Mobs/Enderman.h b/src/Mobs/Enderman.h index aa2eff682..947c32b96 100644 --- a/src/Mobs/Enderman.h +++ b/src/Mobs/Enderman.h @@ -18,11 +18,18 @@ public: CLASS_PROTODEF(cEnderman) virtual void GetDrops(cItems & a_Drops, cEntity * a_Killer = NULL) override; + virtual void CheckEventSeePlayer(void) override; + virtual void CheckEventLostPlayer(void) override; + virtual void EventLosePlayer(void) override; + virtual void Tick(float a_Dt, cChunk & a_Chunk) override; bool IsScreaming(void) const {return m_bIsScreaming; } BLOCKTYPE GetCarriedBlock(void) const {return CarriedBlock; } NIBBLETYPE GetCarriedMeta(void) const {return CarriedMeta; } + /** Returns if the current sky light level is sufficient for the enderman to become aggravated */ + bool CheckLight(void); + private: bool m_bIsScreaming; diff --git a/src/Mobs/Monster.cpp b/src/Mobs/Monster.cpp index 622a67816..73dbcb3c3 100644 --- a/src/Mobs/Monster.cpp +++ b/src/Mobs/Monster.cpp @@ -24,48 +24,58 @@ The strings need to be lowercase (for more efficient comparisons in StringToMobT */ static const struct { - cMonster::eType m_Type; + eMonsterType m_Type; const char * m_lcName; } g_MobTypeNames[] = { - {cMonster::mtBat, "bat"}, - {cMonster::mtBlaze, "blaze"}, - {cMonster::mtCaveSpider, "cavespider"}, - {cMonster::mtChicken, "chicken"}, - {cMonster::mtCow, "cow"}, - {cMonster::mtCreeper, "creeper"}, - {cMonster::mtEnderman, "enderman"}, - {cMonster::mtEnderDragon, "enderdragon"}, - {cMonster::mtGhast, "ghast"}, - {cMonster::mtHorse, "horse"}, - {cMonster::mtIronGolem, "irongolem"}, - {cMonster::mtMagmaCube, "magmacube"}, - {cMonster::mtMooshroom, "mooshroom"}, - {cMonster::mtOcelot, "ocelot"}, - {cMonster::mtPig, "pig"}, - {cMonster::mtSheep, "sheep"}, - {cMonster::mtSilverfish, "silverfish"}, - {cMonster::mtSkeleton, "skeleton"}, - {cMonster::mtSlime, "slime"}, - {cMonster::mtSnowGolem, "snowgolem"}, - {cMonster::mtSpider, "spider"}, - {cMonster::mtSquid, "squid"}, - {cMonster::mtVillager, "villager"}, - {cMonster::mtWitch, "witch"}, - {cMonster::mtWither, "wither"}, - {cMonster::mtWolf, "wolf"}, - {cMonster::mtZombie, "zombie"}, - {cMonster::mtZombiePigman, "zombiepigman"}, + {mtBat, "bat"}, + {mtBlaze, "blaze"}, + {mtCaveSpider, "cavespider"}, + {mtChicken, "chicken"}, + {mtCow, "cow"}, + {mtCreeper, "creeper"}, + {mtEnderman, "enderman"}, + {mtEnderDragon, "enderdragon"}, + {mtGhast, "ghast"}, + {mtHorse, "horse"}, + {mtIronGolem, "irongolem"}, + {mtMagmaCube, "magmacube"}, + {mtMooshroom, "mooshroom"}, + {mtOcelot, "ocelot"}, + {mtPig, "pig"}, + {mtSheep, "sheep"}, + {mtSilverfish, "silverfish"}, + {mtSkeleton, "skeleton"}, + {mtSlime, "slime"}, + {mtSnowGolem, "snowgolem"}, + {mtSpider, "spider"}, + {mtSquid, "squid"}, + {mtVillager, "villager"}, + {mtWitch, "witch"}, + {mtWither, "wither"}, + {mtWolf, "wolf"}, + {mtZombie, "zombie"}, + {mtZombiePigman, "zombiepigman"}, } ; +eMonsterType StringToMobType(const AString & a_MobString) +{ + LOGWARNING("%s: Function is obsolete, use cMonster::StringToMobType() instead", __FUNCTION__); + return cMonster::StringToMobType(a_MobString); +} + + + + + //////////////////////////////////////////////////////////////////////////////// // cMonster: -cMonster::cMonster(const AString & a_ConfigName, eType a_MobType, const AString & a_SoundHurt, const AString & a_SoundDeath, double a_Width, double a_Height) +cMonster::cMonster(const AString & a_ConfigName, eMonsterType a_MobType, const AString & a_SoundHurt, const AString & a_SoundDeath, double a_Width, double a_Height) : super(etMonster, a_Width, a_Height) , m_EMState(IDLE) , m_EMPersonality(AGGRESSIVE) @@ -75,6 +85,8 @@ cMonster::cMonster(const AString & a_ConfigName, eType a_MobType, const AString , m_IdleInterval(0) , m_DestroyTimer(0) , m_MobType(a_MobType) + , m_CustomName("") + , m_CustomNameAlwaysVisible(false) , m_SoundHurt(a_SoundHurt) , m_SoundDeath(a_SoundDeath) , m_AttackRate(3) @@ -89,6 +101,7 @@ cMonster::cMonster(const AString & a_ConfigName, eType a_MobType, const AString , m_DropChanceBoots(0.085f) , m_CanPickUpLoot(true) , m_BurnsInDaylight(false) + , m_RelativeWalkSpeed(1.0) { if (!a_ConfigName.empty()) { @@ -276,11 +289,13 @@ void cMonster::Tick(float a_Dt, cChunk & a_Chunk) if (DoesPosYRequireJump((int)floor(m_Destination.y))) { m_bOnGround = false; - AddSpeedY(5.2); // Jump!! + + // TODO: Change to AddSpeedY once collision detection is fixed - currently, mobs will go into blocks attempting to jump without a teleport + AddPosY(1.2); // Jump!! } } - Vector3f Distance = m_Destination - GetPosition(); + Vector3d Distance = m_Destination - GetPosition(); if (!ReachedDestination() && !ReachedFinalDestination()) // If we haven't reached any sort of destination, move { Distance.y = 0; @@ -288,22 +303,33 @@ void cMonster::Tick(float a_Dt, cChunk & a_Chunk) if (m_bOnGround) { - Distance *= 2.5; + Distance *= 2.5f; + } + else if (IsSwimming()) + { + Distance *= 1.3f; } else { // Don't let the mob move too much if he's falling. - Distance *= 0.25; + Distance *= 0.25f; } + // Apply walk speed: + Distance *= m_RelativeWalkSpeed; + AddSpeedX(Distance.x); AddSpeedZ(Distance.z); + // It's too buggy! + /* if (m_EMState == ESCAPING) - { // Runs Faster when escaping :D otherwise they just walk away + { + // Runs Faster when escaping :D otherwise they just walk away SetSpeedX (GetSpeedX() * 2.f); SetSpeedZ (GetSpeedZ() * 2.f); } + */ } else { @@ -475,50 +501,50 @@ void cMonster::KilledBy(TakeDamageInfo & a_TDI) switch (m_MobType) { // Animals - case cMonster::mtChicken: - case cMonster::mtCow: - case cMonster::mtHorse: - case cMonster::mtPig: - case cMonster::mtSheep: - case cMonster::mtSquid: - case cMonster::mtMooshroom: - case cMonster::mtOcelot: - case cMonster::mtWolf: + case mtChicken: + case mtCow: + case mtHorse: + case mtPig: + case mtSheep: + case mtSquid: + case mtMooshroom: + case mtOcelot: + case mtWolf: { Reward = m_World->GetTickRandomNumber(2) + 1; break; } // Monsters - case cMonster::mtCaveSpider: - case cMonster::mtCreeper: - case cMonster::mtEnderman: - case cMonster::mtGhast: - case cMonster::mtSilverfish: - case cMonster::mtSkeleton: - case cMonster::mtSpider: - case cMonster::mtWitch: - case cMonster::mtZombie: - case cMonster::mtZombiePigman: - case cMonster::mtSlime: - case cMonster::mtMagmaCube: + case mtCaveSpider: + case mtCreeper: + case mtEnderman: + case mtGhast: + case mtSilverfish: + case mtSkeleton: + case mtSpider: + case mtWitch: + case mtZombie: + case mtZombiePigman: + case mtSlime: + case mtMagmaCube: { Reward = 6 + (m_World->GetTickRandomNumber(2)); break; } - case cMonster::mtBlaze: + case mtBlaze: { Reward = 10; break; } // Bosses - case cMonster::mtEnderDragon: + case mtEnderDragon: { Reward = 12000; break; } - case cMonster::mtWither: + case mtWither: { Reward = 50; break; @@ -541,6 +567,25 @@ void cMonster::KilledBy(TakeDamageInfo & a_TDI) +void cMonster::OnRightClicked(cPlayer & a_Player) +{ + super::OnRightClicked(a_Player); + + const cItem & EquippedItem = a_Player.GetEquippedItem(); + if ((EquippedItem.m_ItemType == E_ITEM_NAME_TAG) && !EquippedItem.m_CustomName.empty()) + { + SetCustomName(EquippedItem.m_CustomName); + if (!a_Player.IsGameModeCreative()) + { + a_Player.GetInventory().RemoveOneEquippedItem(); + } + } +} + + + + + // Checks to see if EventSeePlayer should be fired // monster sez: Do I see the player void cMonster::CheckEventSeePlayer(void) @@ -669,6 +714,39 @@ void cMonster::InStateEscaping(float a_Dt) +void cMonster::SetCustomName(const AString & a_CustomName) +{ + m_CustomName = a_CustomName; + + // The maximal length is 64 + if (a_CustomName.length() > 64) + { + m_CustomName = a_CustomName.substr(0, 64); + } + + if (m_World != NULL) + { + m_World->BroadcastEntityMetadata(*this); + } +} + + + + + +void cMonster::SetCustomNameAlwaysVisible(bool a_CustomNameAlwaysVisible) +{ + m_CustomNameAlwaysVisible = a_CustomNameAlwaysVisible; + if (m_World != NULL) + { + m_World->BroadcastEntityMetadata(*this); + } +} + + + + + void cMonster::GetMonsterConfig(const AString & a_Name) { cRoot::Get()->GetMonsterConfig()->AssignAttributes(this, a_Name); @@ -687,7 +765,7 @@ bool cMonster::IsUndead(void) -AString cMonster::MobTypeToString(cMonster::eType a_MobType) +AString cMonster::MobTypeToString(eMonsterType a_MobType) { // Mob types aren't sorted, so we need to search linearly: for (size_t i = 0; i < ARRAYCOUNT(g_MobTypeNames); i++) @@ -706,10 +784,9 @@ AString cMonster::MobTypeToString(cMonster::eType a_MobType) -cMonster::eType cMonster::StringToMobType(const AString & a_Name) +eMonsterType cMonster::StringToMobType(const AString & a_Name) { - AString lcName(a_Name); - StrToLower(lcName); + AString lcName = StrToLower(a_Name); // Binary-search for the lowercase name: int lo = 0, hi = ARRAYCOUNT(g_MobTypeNames) - 1; @@ -748,7 +825,7 @@ cMonster::eType cMonster::StringToMobType(const AString & a_Name) -cMonster::eFamily cMonster::FamilyFromType(eType a_Type) +cMonster::eFamily cMonster::FamilyFromType(eMonsterType a_Type) { // Passive-agressive mobs are counted in mob spawning code as passive @@ -813,7 +890,7 @@ int cMonster::GetSpawnDelay(cMonster::eFamily a_MobFamily) -cMonster * cMonster::NewMonsterFromType(cMonster::eType a_MobType) +cMonster * cMonster::NewMonsterFromType(eMonsterType a_MobType) { cFastRandom Random; cMonster * toReturn = NULL; @@ -1015,7 +1092,7 @@ void cMonster::HandleDaylightBurning(cChunk & a_Chunk) (a_Chunk.GetBlock(RelX, RelY, RelZ) != E_BLOCK_SOULSAND) && // Not on soulsand (GetWorld()->GetTimeOfDay() < (12000 + 1000)) && // It is nighttime !IsOnFire() && // Not already burning - GetWorld()->IsWeatherWetAt(POSX_TOINT, POSZ_TOINT) // Not raining + GetWorld()->IsWeatherSunnyAt(POSX_TOINT, POSZ_TOINT) // Not raining ) { // Burn for 100 ticks, then decide again diff --git a/src/Mobs/Monster.h b/src/Mobs/Monster.h index cdbd26c09..9fd67d67c 100644 --- a/src/Mobs/Monster.h +++ b/src/Mobs/Monster.h @@ -6,6 +6,7 @@ #include "../BlockID.h" #include "../Item.h" #include "../Enchantments.h" +#include "MonsterTypes.h" @@ -23,41 +24,6 @@ class cMonster : { typedef cPawn super; public: - /// This identifies individual monster type, as well as their network type-ID - enum eType - { - mtInvalidType = -1, - - mtBat = E_META_SPAWN_EGG_BAT, - mtBlaze = E_META_SPAWN_EGG_BLAZE, - mtCaveSpider = E_META_SPAWN_EGG_CAVE_SPIDER, - mtChicken = E_META_SPAWN_EGG_CHICKEN, - mtCow = E_META_SPAWN_EGG_COW, - mtCreeper = E_META_SPAWN_EGG_CREEPER, - mtEnderDragon = E_META_SPAWN_EGG_ENDER_DRAGON, - mtEnderman = E_META_SPAWN_EGG_ENDERMAN, - mtGhast = E_META_SPAWN_EGG_GHAST, - mtGiant = E_META_SPAWN_EGG_GIANT, - mtHorse = E_META_SPAWN_EGG_HORSE, - mtIronGolem = E_META_SPAWN_EGG_IRON_GOLEM, - mtMagmaCube = E_META_SPAWN_EGG_MAGMA_CUBE, - mtMooshroom = E_META_SPAWN_EGG_MOOSHROOM, - mtOcelot = E_META_SPAWN_EGG_OCELOT, - mtPig = E_META_SPAWN_EGG_PIG, - mtSheep = E_META_SPAWN_EGG_SHEEP, - mtSilverfish = E_META_SPAWN_EGG_SILVERFISH, - mtSkeleton = E_META_SPAWN_EGG_SKELETON, - mtSlime = E_META_SPAWN_EGG_SLIME, - mtSnowGolem = E_META_SPAWN_EGG_SNOW_GOLEM, - mtSpider = E_META_SPAWN_EGG_SPIDER, - mtSquid = E_META_SPAWN_EGG_SQUID, - mtVillager = E_META_SPAWN_EGG_VILLAGER, - mtWitch = E_META_SPAWN_EGG_WITCH, - mtWither = E_META_SPAWN_EGG_WITHER, - mtWolf = E_META_SPAWN_EGG_WOLF, - mtZombie = E_META_SPAWN_EGG_ZOMBIE, - mtZombiePigman = E_META_SPAWN_EGG_ZOMBIE_PIGMAN, - } ; enum eFamily { @@ -80,7 +46,7 @@ public: 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 */ - cMonster(const AString & a_ConfigName, eType a_MobType, const AString & a_SoundHurt, const AString & a_SoundDeath, double a_Width, double a_Height); + cMonster(const AString & a_ConfigName, eMonsterType a_MobType, const AString & a_SoundHurt, const AString & a_SoundDeath, double a_Width, double a_Height); CLASS_PROTODEF(cMonster) @@ -92,11 +58,13 @@ public: virtual void KilledBy(TakeDamageInfo & a_TDI) override; + virtual void OnRightClicked(cPlayer & a_Player) override; + virtual void MoveToPosition(const Vector3d & a_Position); // tolua_export virtual bool ReachedDestination(void); // tolua_begin - eType GetMobType(void) const {return m_MobType; } + eMonsterType GetMobType(void) const {return m_MobType; } eFamily GetMobFamily(void) const; // tolua_end @@ -138,21 +106,41 @@ public: /// Sets whether the mob burns in daylight. Only evaluated at next burn-decision tick void SetBurnsInDaylight(bool a_BurnsInDaylight) { m_BurnsInDaylight = a_BurnsInDaylight; } + double GetRelativeWalkSpeed(void) const { return m_RelativeWalkSpeed; } // tolua_export + void SetRelativeWalkSpeed(double a_WalkSpeed) { m_RelativeWalkSpeed = a_WalkSpeed; } // tolua_export + // Overridables to handle ageable mobs virtual bool IsBaby (void) const { return false; } virtual bool IsTame (void) const { return false; } virtual bool IsSitting (void) const { return false; } // tolua_begin - + + /** Returns true if the monster has a custom name. */ + bool HasCustomName(void) const { return !m_CustomName.empty(); } + + /** Gets the custom name of the monster. If no custom name is set, the function returns an empty string. */ + const AString & GetCustomName(void) const { return m_CustomName; } + + /** 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. */ + 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. + If it's false, you only see the name when you sight the mob. If it's true, you always see the custom name. */ + void SetCustomNameAlwaysVisible(bool a_CustomNameAlwaysVisible); + /// Translates MobType enum to a string, empty string if unknown - static AString MobTypeToString(eType a_MobType); + static AString MobTypeToString(eMonsterType a_MobType); /// Translates MobType string to the enum, mtInvalidType if not recognized - static eType StringToMobType(const AString & a_MobTypeName); + static eMonsterType StringToMobType(const AString & a_MobTypeName); /// Returns the mob family based on the type - static eFamily FamilyFromType(eType a_MobType); + static eFamily FamilyFromType(eMonsterType a_MobType); /// Returns the spawn delay (number of game ticks between spawn attempts) for the given mob family static int GetSpawnDelay(cMonster::eFamily a_MobFamily); @@ -163,7 +151,7 @@ public: a_MobType is the type of the mob to be created Asserts and returns null if mob type is not specified */ - static cMonster * NewMonsterFromType(eType a_MobType); + static cMonster * NewMonsterFromType(eMonsterType a_MobType); protected: @@ -227,7 +215,9 @@ protected: float m_IdleInterval; float m_DestroyTimer; - eType m_MobType; + eMonsterType m_MobType; + AString m_CustomName; + bool m_CustomNameAlwaysVisible; AString m_SoundHurt; AString m_SoundDeath; @@ -248,6 +238,8 @@ protected: void HandleDaylightBurning(cChunk & a_Chunk); bool m_BurnsInDaylight; + double m_RelativeWalkSpeed; + /** Adds a random number of a_Item between a_Min and a_Max to itemdrops a_Drops*/ void AddRandomDropItem(cItems & a_Drops, unsigned int a_Min, unsigned int a_Max, short a_Item, short a_ItemHealth = 0); diff --git a/src/Mobs/MonsterTypes.h b/src/Mobs/MonsterTypes.h new file mode 100644 index 000000000..852eb3446 --- /dev/null +++ b/src/Mobs/MonsterTypes.h @@ -0,0 +1,54 @@ + +#pragma once + +/// This identifies individual monster type, as well as their network type-ID +// tolua_begin +enum eMonsterType +{ + mtInvalidType = -1, + + mtBat = E_META_SPAWN_EGG_BAT, + mtBlaze = E_META_SPAWN_EGG_BLAZE, + mtCaveSpider = E_META_SPAWN_EGG_CAVE_SPIDER, + mtChicken = E_META_SPAWN_EGG_CHICKEN, + mtCow = E_META_SPAWN_EGG_COW, + mtCreeper = E_META_SPAWN_EGG_CREEPER, + mtEnderDragon = E_META_SPAWN_EGG_ENDER_DRAGON, + mtEnderman = E_META_SPAWN_EGG_ENDERMAN, + mtGhast = E_META_SPAWN_EGG_GHAST, + mtGiant = E_META_SPAWN_EGG_GIANT, + mtHorse = E_META_SPAWN_EGG_HORSE, + mtIronGolem = E_META_SPAWN_EGG_IRON_GOLEM, + mtMagmaCube = E_META_SPAWN_EGG_MAGMA_CUBE, + mtMooshroom = E_META_SPAWN_EGG_MOOSHROOM, + mtOcelot = E_META_SPAWN_EGG_OCELOT, + mtPig = E_META_SPAWN_EGG_PIG, + mtSheep = E_META_SPAWN_EGG_SHEEP, + mtSilverfish = E_META_SPAWN_EGG_SILVERFISH, + mtSkeleton = E_META_SPAWN_EGG_SKELETON, + mtSlime = E_META_SPAWN_EGG_SLIME, + mtSnowGolem = E_META_SPAWN_EGG_SNOW_GOLEM, + mtSpider = E_META_SPAWN_EGG_SPIDER, + mtSquid = E_META_SPAWN_EGG_SQUID, + mtVillager = E_META_SPAWN_EGG_VILLAGER, + mtWitch = E_META_SPAWN_EGG_WITCH, + mtWither = E_META_SPAWN_EGG_WITHER, + mtWolf = E_META_SPAWN_EGG_WOLF, + mtZombie = E_META_SPAWN_EGG_ZOMBIE, + mtZombiePigman = E_META_SPAWN_EGG_ZOMBIE_PIGMAN, +} ; + + + + + +/** Translates a mob string ("ocelot") to mobtype (mtOcelot). +OBSOLETE, use cMonster::StringToMobType() instead. +Implemented in Monster.cpp. */ +extern eMonsterType StringToMobType(const AString & a_MobString); + +// tolua_end + + + + diff --git a/src/Mobs/Mooshroom.cpp b/src/Mobs/Mooshroom.cpp index 81bd3e3b4..99958720f 100644 --- a/src/Mobs/Mooshroom.cpp +++ b/src/Mobs/Mooshroom.cpp @@ -67,7 +67,7 @@ void cMooshroom::OnRightClicked(cPlayer & a_Player) cItems Drops; Drops.push_back(cItem(E_BLOCK_RED_MUSHROOM, 5, 0)); m_World->SpawnItemPickups(Drops, GetPosX(), GetPosY(), GetPosZ(), 10); - m_World->SpawnMob(GetPosX(), GetPosY(), GetPosZ(), cMonster::mtCow); + m_World->SpawnMob(GetPosX(), GetPosY(), GetPosZ(), mtCow); Destroy(); } break; } diff --git a/src/Mobs/PassiveAggressiveMonster.cpp b/src/Mobs/PassiveAggressiveMonster.cpp index 24501b1ba..e0cc2fd21 100644 --- a/src/Mobs/PassiveAggressiveMonster.cpp +++ b/src/Mobs/PassiveAggressiveMonster.cpp @@ -9,7 +9,7 @@ -cPassiveAggressiveMonster::cPassiveAggressiveMonster(const AString & a_ConfigName, eType a_MobType, const AString & a_SoundHurt, const AString & a_SoundDeath, double a_Width, double a_Height) : +cPassiveAggressiveMonster::cPassiveAggressiveMonster(const AString & a_ConfigName, eMonsterType a_MobType, const AString & a_SoundHurt, const AString & a_SoundDeath, double a_Width, double a_Height) : super(a_ConfigName, a_MobType, a_SoundHurt, a_SoundDeath, a_Width, a_Height) { m_EMPersonality = PASSIVE; diff --git a/src/Mobs/PassiveAggressiveMonster.h b/src/Mobs/PassiveAggressiveMonster.h index a0da50e8e..72f472281 100644 --- a/src/Mobs/PassiveAggressiveMonster.h +++ b/src/Mobs/PassiveAggressiveMonster.h @@ -13,7 +13,7 @@ class cPassiveAggressiveMonster : typedef cAggressiveMonster super; public: - cPassiveAggressiveMonster(const AString & a_ConfigName, eType a_MobType, const AString & a_SoundHurt, const AString & a_SoundDeath, double a_Width, double a_Height); + cPassiveAggressiveMonster(const AString & a_ConfigName, eMonsterType a_MobType, const AString & a_SoundHurt, const AString & a_SoundDeath, double a_Width, double a_Height); virtual bool DoTakeDamage(TakeDamageInfo & a_TDI) override; } ; diff --git a/src/Mobs/PassiveMonster.cpp b/src/Mobs/PassiveMonster.cpp index 2861d7314..be3043e3d 100644 --- a/src/Mobs/PassiveMonster.cpp +++ b/src/Mobs/PassiveMonster.cpp @@ -8,7 +8,7 @@ -cPassiveMonster::cPassiveMonster(const AString & a_ConfigName, eType a_MobType, const AString & a_SoundHurt, const AString & a_SoundDeath, double a_Width, double a_Height) : +cPassiveMonster::cPassiveMonster(const AString & a_ConfigName, eMonsterType a_MobType, const AString & a_SoundHurt, const AString & a_SoundDeath, double a_Width, double a_Height) : super(a_ConfigName, a_MobType, a_SoundHurt, a_SoundDeath, a_Width, a_Height) { m_EMPersonality = PASSIVE; diff --git a/src/Mobs/PassiveMonster.h b/src/Mobs/PassiveMonster.h index 70574585a..9221d9a6e 100644 --- a/src/Mobs/PassiveMonster.h +++ b/src/Mobs/PassiveMonster.h @@ -13,7 +13,7 @@ class cPassiveMonster : typedef cMonster super; public: - cPassiveMonster(const AString & a_ConfigName, eType a_MobType, const AString & a_SoundHurt, const AString & a_SoundDeath, double a_Width, double a_Height); + cPassiveMonster(const AString & a_ConfigName, eMonsterType a_MobType, const AString & a_SoundHurt, const AString & a_SoundDeath, double a_Width, double a_Height); virtual void Tick(float a_Dt, cChunk & a_Chunk) override; diff --git a/src/Mobs/Sheep.cpp b/src/Mobs/Sheep.cpp index 9fb47201d..cbb33cb90 100644 --- a/src/Mobs/Sheep.cpp +++ b/src/Mobs/Sheep.cpp @@ -39,6 +39,13 @@ void cSheep::GetDrops(cItems & a_Drops, cEntity * a_Killer) { a_Drops.push_back(cItem(E_BLOCK_WOOL, 1, m_WoolColor)); } + + int LootingLevel = 0; + if (a_Killer != NULL) + { + LootingLevel = a_Killer->GetEquippedWeapon().m_Enchantments.GetLevel(cEnchantments::enchLooting); + } + AddRandomDropItem(a_Drops, 1, 3 + LootingLevel, IsOnFire() ? E_ITEM_COOKED_MUTTON : E_ITEM_RAW_MUTTON); } @@ -47,6 +54,8 @@ void cSheep::GetDrops(cItems & a_Drops, cEntity * a_Killer) void cSheep::OnRightClicked(cPlayer & a_Player) { + super::OnRightClicked(a_Player); + const cItem & EquippedItem = a_Player.GetEquippedItem(); if ((EquippedItem.m_ItemType == E_ITEM_SHEARS) && !IsSheared() && !IsBaby()) { diff --git a/src/Mobs/Villager.cpp b/src/Mobs/Villager.cpp index 1cdac7c74..0efd5501e 100644 --- a/src/Mobs/Villager.cpp +++ b/src/Mobs/Villager.cpp @@ -109,11 +109,11 @@ void cVillager::HandleFarmerPrepareFarmCrops() Surrounding.Read( m_World, (int) GetPosX() - 5, - (int) GetPosX() + 5, + (int) GetPosX() + 6, (int) GetPosY() - 3, - (int) GetPosY() + 3, + (int) GetPosY() + 4, (int) GetPosZ() - 5, - (int) GetPosZ() + 5 + (int) GetPosZ() + 6 ); for (int I = 0; I < 5; I++) diff --git a/src/Mobs/Villager.h b/src/Mobs/Villager.h index aa81f0790..d3a38dbf0 100644 --- a/src/Mobs/Villager.h +++ b/src/Mobs/Villager.h @@ -2,7 +2,7 @@ #pragma once #include "PassiveMonster.h" - +#include "Blocks/ChunkInterface.h" diff --git a/src/Mobs/Wolf.cpp b/src/Mobs/Wolf.cpp index 5bb97d30e..4fe1ff1d6 100644 --- a/src/Mobs/Wolf.cpp +++ b/src/Mobs/Wolf.cpp @@ -68,6 +68,7 @@ void cWolf::OnRightClicked(cPlayer & a_Player) { if (!IsTame() && !IsAngry()) { + // If the player is holding a bone, try to tame the wolf: if (a_Player.GetEquippedItem().m_ItemType == E_ITEM_BONE) { if (!a_Player.IsGameModeCreative()) @@ -77,14 +78,16 @@ void cWolf::OnRightClicked(cPlayer & a_Player) if (m_World->GetTickRandomNumber(7) == 0) { + // Taming succeeded SetMaxHealth(20); SetIsTame(true); - SetOwner(a_Player.GetName()); + SetOwner(a_Player.GetName(), a_Player.GetUUID()); m_World->BroadcastEntityStatus(*this, esWolfTamed); m_World->BroadcastParticleEffect("heart", (float) GetPosX(), (float) GetPosY(), (float) GetPosZ(), 0, 0, 0, 0, 5); } else { + // Taming failed m_World->BroadcastEntityStatus(*this, esWolfTaming); m_World->BroadcastParticleEffect("smoke", (float) GetPosX(), (float) GetPosY(), (float) GetPosZ(), 0, 0, 0, 0, 5); } @@ -92,6 +95,7 @@ void cWolf::OnRightClicked(cPlayer & a_Player) } else if (IsTame()) { + // Feed the wolf, restoring its health, or dye its collar: switch (a_Player.GetEquippedItem().m_ItemType) { case E_ITEM_RAW_BEEF: diff --git a/src/Mobs/Wolf.h b/src/Mobs/Wolf.h index 2e83db701..7500854f8 100644 --- a/src/Mobs/Wolf.h +++ b/src/Mobs/Wolf.h @@ -29,7 +29,8 @@ public: bool IsTame (void) const { return m_IsTame; } bool IsBegging (void) const { return m_IsBegging; } bool IsAngry (void) const { return m_IsAngry; } - AString GetOwner (void) const { return m_OwnerName; } + AString GetOwnerName (void) const { return m_OwnerName; } + AString GetOwnerUUID (void) const { return m_OwnerUUID; } int GetCollarColor(void) const { return m_CollarColor; } // Set functions @@ -37,8 +38,12 @@ public: void SetIsTame (bool a_IsTame) { m_IsTame = a_IsTame; } void SetIsBegging (bool a_IsBegging) { m_IsBegging = a_IsBegging; } void SetIsAngry (bool a_IsAngry) { m_IsAngry = a_IsAngry; } - void SetOwner (const AString & a_NewOwner) { m_OwnerName = a_NewOwner; } void SetCollarColor(int a_CollarColor) { m_CollarColor = a_CollarColor; } + void SetOwner (const AString & a_NewOwnerName, const AString & a_NewOwnerUUID) + { + m_OwnerName = a_NewOwnerName; + m_OwnerUUID = a_NewOwnerUUID; + } protected: @@ -47,6 +52,7 @@ protected: bool m_IsBegging; bool m_IsAngry; AString m_OwnerName; + AString m_OwnerUUID; int m_CollarColor; } ; |