From c836b52dd1b8d6a2999721f235e6c2b6079b266c Mon Sep 17 00:00:00 2001 From: Masy98 Date: Thu, 18 Dec 2014 19:30:32 +0100 Subject: [PATCH] Added Entity Guardian --- MCServer/Plugins/ProtectionAreas | 2 +- Tools/AnvilStats/Utils.cpp | 1 + Tools/AnvilStats/Utils.h | 1 + src/BlockID.h | 1 + src/Items/ItemSpawnEgg.h | 1 + src/MobSpawner.cpp | 6 +++ src/Mobs/CMakeLists.txt | 2 + src/Mobs/Guardian.cpp | 65 +++++++++++++++++++++++++ src/Mobs/Guardian.h | 31 ++++++++++++ src/Mobs/IncludeAllMonsters.h | 1 + src/Mobs/Monster.cpp | 4 ++ src/Mobs/Monster.h | 2 +- src/Mobs/MonsterTypes.h | 1 + src/World.cpp | 2 +- src/WorldStorage/NBTChunkSerializer.cpp | 2 + src/WorldStorage/WSSAnvil.cpp | 24 +++++++++ src/WorldStorage/WSSAnvil.h | 1 + 17 files changed, 144 insertions(+), 3 deletions(-) create mode 100644 src/Mobs/Guardian.cpp create mode 100644 src/Mobs/Guardian.h diff --git a/MCServer/Plugins/ProtectionAreas b/MCServer/Plugins/ProtectionAreas index 624580e5b..7765048fa 160000 --- a/MCServer/Plugins/ProtectionAreas +++ b/MCServer/Plugins/ProtectionAreas @@ -1 +1 @@ -Subproject commit 624580e5b522ba2799dfe5b5902b4002b1a8da3e +Subproject commit 7765048fa740b8f119db72a4ccc546504f86b2ab diff --git a/Tools/AnvilStats/Utils.cpp b/Tools/AnvilStats/Utils.cpp index d7543cb4c..f5b3b58fb 100644 --- a/Tools/AnvilStats/Utils.cpp +++ b/Tools/AnvilStats/Utils.cpp @@ -26,6 +26,7 @@ struct {entEnderman, "Enderman"}, {entGhast, "Ghast"}, {entGiant, "Giant"}, + {entGuardian, "Guardian"}, {entLavaSlime, "LavaSlime"}, {entMushroomCow, "MushroomCow"}, {entOzelot, "Ozelot"}, diff --git a/Tools/AnvilStats/Utils.h b/Tools/AnvilStats/Utils.h index ab2d7166c..4c4e89f26 100644 --- a/Tools/AnvilStats/Utils.h +++ b/Tools/AnvilStats/Utils.h @@ -25,6 +25,7 @@ enum eEntityType entEnderman, entGhast, entGiant, + entGuardian, entLavaSlime, entMushroomCow, entOzelot, diff --git a/src/BlockID.h b/src/BlockID.h index 8f2cee02e..bfb6b8d6d 100644 --- a/src/BlockID.h +++ b/src/BlockID.h @@ -959,6 +959,7 @@ enum E_META_SPAWN_EGG_WITHER = 64, E_META_SPAWN_EGG_BAT = 65, E_META_SPAWN_EGG_WITCH = 66, + E_META_SPAWN_EGG_GUARDIAN = 68, E_META_SPAWN_EGG_PIG = 90, E_META_SPAWN_EGG_SHEEP = 91, E_META_SPAWN_EGG_COW = 92, diff --git a/src/Items/ItemSpawnEgg.h b/src/Items/ItemSpawnEgg.h index 617ecd808..2f28ec6eb 100644 --- a/src/Items/ItemSpawnEgg.h +++ b/src/Items/ItemSpawnEgg.h @@ -64,6 +64,7 @@ public: case E_META_SPAWN_EGG_CREEPER: return mtCreeper; case E_META_SPAWN_EGG_ENDERMAN: return mtEnderman; case E_META_SPAWN_EGG_GHAST: return mtGhast; + case E_META_SPAWN_EGG_GUARDIAN: return mtGuardian; case E_META_SPAWN_EGG_HORSE: return mtHorse; case E_META_SPAWN_EGG_MAGMA_CUBE: return mtMagmaCube; case E_META_SPAWN_EGG_MOOSHROOM: return mtMooshroom; diff --git a/src/MobSpawner.cpp b/src/MobSpawner.cpp index ee9e569a7..bd34d8fcd 100644 --- a/src/MobSpawner.cpp +++ b/src/MobSpawner.cpp @@ -83,6 +83,7 @@ eMonsterType cMobSpawner::ChooseMobType(EMCSBiome a_Biome) addIfAllowed(mtSkeleton, allowedMobs); addIfAllowed(mtCreeper, allowedMobs); addIfAllowed(mtSquid, allowedMobs); + addIfAllowed(mtGuardian, allowedMobs); if ((a_Biome != biDesert) && (a_Biome != biBeach) && (a_Biome != biOcean)) { @@ -144,6 +145,11 @@ bool cMobSpawner::CanSpawnHere(cChunk * a_Chunk, int a_RelX, int a_RelY, int a_R switch (a_MobType) { + case mtGuardian: + { + return IsBlockWater(TargetBlock) && (a_RelY >= 45) && (a_RelY <= 62); + } + case mtSquid: { return IsBlockWater(TargetBlock) && (a_RelY >= 45) && (a_RelY <= 62); diff --git a/src/Mobs/CMakeLists.txt b/src/Mobs/CMakeLists.txt index bbbb9287a..c1ac2de32 100644 --- a/src/Mobs/CMakeLists.txt +++ b/src/Mobs/CMakeLists.txt @@ -16,6 +16,7 @@ SET (SRCS Enderman.cpp Ghast.cpp Giant.cpp + Guardian.cpp Horse.cpp IronGolem.cpp MagmaCube.cpp @@ -49,6 +50,7 @@ SET (HDRS Enderman.h Ghast.h Giant.h + Guardian.h Horse.h IncludeAllMonsters.h IronGolem.h diff --git a/src/Mobs/Guardian.cpp b/src/Mobs/Guardian.cpp new file mode 100644 index 000000000..166057865 --- /dev/null +++ b/src/Mobs/Guardian.cpp @@ -0,0 +1,65 @@ + +#include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules + +#include "Guardian.h" +#include "../Vector3.h" +#include "../Chunk.h" + + + + + +cGuardian::cGuardian(void) : + super("Guardian", mtGuardian, "mob.guardian.idle", "mob.guardian.death", 0.95, 0.95) +{ +} + + + + + +void cGuardian::GetDrops(cItems & a_Drops, cEntity * a_Killer) +{ + // Drops 0-3 Ink Sacs + int LootingLevel = 0; + if (a_Killer != nullptr) + { + LootingLevel = a_Killer->GetEquippedWeapon().m_Enchantments.GetLevel(cEnchantments::enchLooting); + } + AddRandomDropItem(a_Drops, 0, 2 + LootingLevel, E_ITEM_PRISMARINE_SHARD); + AddRandomDropItem(a_Drops, 0, 1 + LootingLevel, E_ITEM_RAW_FISH); + AddRandomDropItem(a_Drops, 0, 1 + LootingLevel, E_ITEM_PRISMARINE_CRYSTALS); // ToDo: Prismarine Crystals only drop if the raw fish drop is 0 +} + + + + + +void cGuardian::Tick(float a_Dt, cChunk & a_Chunk) +{ + // We must first process current location, and only then tick, otherwise we risk processing a location in a chunk + // that is not where the entity currently resides (FS #411) + + Vector3d Pos = GetPosition(); + + // TODO: Not a real behavior, but cool :D + int RelY = (int)floor(Pos.y); + if ((RelY < 0) || (RelY >= cChunkDef::Height)) + { + return; + } + int RelX = (int)floor(Pos.x) - a_Chunk.GetPosX() * cChunkDef::Width; + int RelZ = (int)floor(Pos.z) - a_Chunk.GetPosZ() * cChunkDef::Width; + BLOCKTYPE BlockType; + if (a_Chunk.UnboundedRelGetBlockType(RelX, RelY, RelZ, BlockType) && !IsBlockWater(BlockType) && !IsOnFire()) + { + // Burn for 10 ticks, then decide again + StartBurning(10); + } + + super::Tick(a_Dt, a_Chunk); +} + + + + diff --git a/src/Mobs/Guardian.h b/src/Mobs/Guardian.h new file mode 100644 index 000000000..50c034036 --- /dev/null +++ b/src/Mobs/Guardian.h @@ -0,0 +1,31 @@ + +#pragma once + +#include "AggressiveMonster.h" + + + + + +class cGuardian : + public cAggressiveMonster +{ + typedef cAggressiveMonster super; + +public: + cGuardian(); + + virtual void Tick(float a_Dt, cChunk & a_Chunk) override; + + CLASS_PROTODEF(cGuardian) + + virtual void GetDrops(cItems & a_Drops, cEntity * a_Killer = nullptr) override; + + // Guardians do not drown (or float) + virtual void HandleAir(void) override {} + virtual void SetSwimState(cChunk & a_Chunk) override {} +} ; + + + + diff --git a/src/Mobs/IncludeAllMonsters.h b/src/Mobs/IncludeAllMonsters.h index 3460db993..f5eb9dcc3 100644 --- a/src/Mobs/IncludeAllMonsters.h +++ b/src/Mobs/IncludeAllMonsters.h @@ -8,6 +8,7 @@ #include "EnderDragon.h" #include "Ghast.h" #include "Giant.h" +#include "Guardian.h" #include "Horse.h" #include "IronGolem.h" #include "MagmaCube.h" diff --git a/src/Mobs/Monster.cpp b/src/Mobs/Monster.cpp index 7b8f763af..963ca628c 100644 --- a/src/Mobs/Monster.cpp +++ b/src/Mobs/Monster.cpp @@ -38,6 +38,7 @@ static const struct {mtEnderman, "enderman", "Enderman"}, {mtEnderDragon, "enderdragon", "EnderDragon"}, {mtGhast, "ghast", "Ghast"}, + {mtGuardian, "guardian", "Guardian"}, {mtHorse, "horse", "EntityHorse"}, {mtIronGolem, "irongolem", "VillagerGolem"}, {mtMagmaCube, "magmacube", "LavaSlime"}, @@ -513,6 +514,7 @@ void cMonster::KilledBy(TakeDamageInfo & a_TDI) case mtCreeper: case mtEnderman: case mtGhast: + case mtGuardian: case mtSilverfish: case mtSkeleton: case mtSpider: @@ -842,6 +844,7 @@ cMonster::eFamily cMonster::FamilyFromType(eMonsterType a_Type) case mtEnderman: return mfHostile; case mtGhast: return mfHostile; case mtGiant: return mfNoSpawn; + case mtGuardian: return mfNoSpawn; // Just because they have special spawning conditions. If Watertemples have been added, this needs to be edited! case mtHorse: return mfPassive; case mtIronGolem: return mfPassive; case mtMagmaCube: return mfHostile; @@ -955,6 +958,7 @@ cMonster * cMonster::NewMonsterFromType(eMonsterType a_MobType) case mtEnderman: toReturn = new cEnderman(); break; case mtGhast: toReturn = new cGhast(); break; case mtGiant: toReturn = new cGiant(); break; + case mtGuardian: toReturn = new cGuardian(); break; case mtIronGolem: toReturn = new cIronGolem(); break; case mtMooshroom: toReturn = new cMooshroom(); break; case mtOcelot: toReturn = new cOcelot(); break; diff --git a/src/Mobs/Monster.h b/src/Mobs/Monster.h index f04e45ac6..fb1bc550d 100644 --- a/src/Mobs/Monster.h +++ b/src/Mobs/Monster.h @@ -30,7 +30,7 @@ public: mfHostile = 0, // Spider, Zombies ... mfPassive = 1, // Cows, Pigs mfAmbient = 2, // Bats - mfWater = 3, // Squid + mfWater = 3, // Squid, Guardian mfNoSpawn, mfUnhandled, // Nothing. Be sure this is the last and the others are in order diff --git a/src/Mobs/MonsterTypes.h b/src/Mobs/MonsterTypes.h index dc6dd3992..50fcf971a 100644 --- a/src/Mobs/MonsterTypes.h +++ b/src/Mobs/MonsterTypes.h @@ -18,6 +18,7 @@ enum eMonsterType mtEnderman = E_META_SPAWN_EGG_ENDERMAN, mtGhast = E_META_SPAWN_EGG_GHAST, mtGiant = E_META_SPAWN_EGG_GIANT, + mtGuardian = E_META_SPAWN_EGG_GUARDIAN, mtHorse = E_META_SPAWN_EGG_HORSE, mtIronGolem = E_META_SPAWN_EGG_IRON_GOLEM, mtMagmaCube = E_META_SPAWN_EGG_MAGMA_CUBE, diff --git a/src/World.cpp b/src/World.cpp index 1bee6e344..99701e11b 100644 --- a/src/World.cpp +++ b/src/World.cpp @@ -776,7 +776,7 @@ void cWorld::InitialiseAndLoadMobSpawningValues(cIniFile & a_IniFile) AString DefaultMonsters; switch (m_Dimension) { - case dimOverworld: DefaultMonsters = "bat, cavespider, chicken, cow, creeper, enderman, horse, mooshroom, ocelot, pig, sheep, silverfish, skeleton, slime, spider, squid, wolf, zombie"; break; + case dimOverworld: DefaultMonsters = "bat, cavespider, chicken, cow, creeper, enderman, guardian, horse, mooshroom, ocelot, pig, sheep, silverfish, skeleton, slime, spider, squid, wolf, zombie"; break; case dimNether: DefaultMonsters = "blaze, ghast, magmacube, skeleton, zombie, zombiepigman"; break; case dimEnd: DefaultMonsters = "enderman"; break; case dimNotSet: ASSERT(!"Dimension not set"); break; diff --git a/src/WorldStorage/NBTChunkSerializer.cpp b/src/WorldStorage/NBTChunkSerializer.cpp index 432e122b5..9d8e20b0b 100644 --- a/src/WorldStorage/NBTChunkSerializer.cpp +++ b/src/WorldStorage/NBTChunkSerializer.cpp @@ -495,6 +495,7 @@ void cNBTChunkSerializer::AddMonsterEntity(cMonster * a_Monster) case mtEnderman: EntityClass = "Enderman"; break; case mtGhast: EntityClass = "Ghast"; break; case mtGiant: EntityClass = "Giant"; break; + case mtGuardian: EntityClass = "Guardian"; break; case mtHorse: EntityClass = "Horse"; break; case mtIronGolem: EntityClass = "VillagerGolem"; break; case mtMagmaCube: EntityClass = "LavaSlime"; break; @@ -627,6 +628,7 @@ void cNBTChunkSerializer::AddMonsterEntity(cMonster * a_Monster) case mtEnderDragon: case mtGhast: case mtGiant: + case mtGuardian: case mtIronGolem: case mtMooshroom: case mtOcelot: diff --git a/src/WorldStorage/WSSAnvil.cpp b/src/WorldStorage/WSSAnvil.cpp index af65db700..a045497bc 100755 --- a/src/WorldStorage/WSSAnvil.cpp +++ b/src/WorldStorage/WSSAnvil.cpp @@ -1410,6 +1410,10 @@ void cWSSAnvil::LoadEntityFromNBT(cEntityList & a_Entities, const cParsedNBT & a { LoadGiantFromNBT(a_Entities, a_NBT, a_EntityTagIdx); } + else if (strncmp(a_IDTag, "Guardian", a_IDTagLength) == 0) + { + LoadGuardianFromNBT(a_Entities, a_NBT, a_EntityTagIdx); + } else if (strncmp(a_IDTag, "Horse", a_IDTagLength) == 0) { LoadHorseFromNBT(a_Entities, a_NBT, a_EntityTagIdx); @@ -2197,6 +2201,26 @@ void cWSSAnvil::LoadGiantFromNBT(cEntityList & a_Entities, const cParsedNBT & a_ +void cWSSAnvil::LoadGuardianFromNBT(cEntityList & a_Entities, const cParsedNBT & a_NBT, int a_TagIdx) +{ + std::unique_ptr Monster(new cGuardian()); + if (!LoadEntityBaseFromNBT(*Monster.get(), a_NBT, a_TagIdx)) + { + return; + } + + if (!LoadMonsterBaseFromNBT(*Monster.get(), a_NBT, a_TagIdx)) + { + return; + } + + a_Entities.push_back(Monster.release()); +} + + + + + void cWSSAnvil::LoadHorseFromNBT(cEntityList & a_Entities, const cParsedNBT & a_NBT, int a_TagIdx) { int TypeIdx = a_NBT.FindChildByName(a_TagIdx, "Type"); diff --git a/src/WorldStorage/WSSAnvil.h b/src/WorldStorage/WSSAnvil.h index 974ba932e..7bcdd259e 100755 --- a/src/WorldStorage/WSSAnvil.h +++ b/src/WorldStorage/WSSAnvil.h @@ -191,6 +191,7 @@ protected: void LoadEndermanFromNBT (cEntityList & a_Entities, const cParsedNBT & a_NBT, int a_TagIdx); void LoadGhastFromNBT (cEntityList & a_Entities, const cParsedNBT & a_NBT, int a_TagIdx); void LoadGiantFromNBT (cEntityList & a_Entities, const cParsedNBT & a_NBT, int a_TagIdx); + void LoadGuardianFromNBT (cEntityList & a_Entities, const cParsedNBT & a_NBT, int a_TagIdx); void LoadHorseFromNBT (cEntityList & a_Entities, const cParsedNBT & a_NBT, int a_TagIdx); void LoadIronGolemFromNBT (cEntityList & a_Entities, const cParsedNBT & a_NBT, int a_TagIdx); void LoadMagmaCubeFromNBT (cEntityList & a_Entities, const cParsedNBT & a_NBT, int a_TagIdx);