diff options
Diffstat (limited to 'Minecraft.World/Bat.cpp')
| -rw-r--r-- | Minecraft.World/Bat.cpp | 258 |
1 files changed, 258 insertions, 0 deletions
diff --git a/Minecraft.World/Bat.cpp b/Minecraft.World/Bat.cpp new file mode 100644 index 00000000..d3bd3521 --- /dev/null +++ b/Minecraft.World/Bat.cpp @@ -0,0 +1,258 @@ +#include "stdafx.h" +#include "net.minecraft.world.entity.h" +#include "net.minecraft.world.entity.ai.attributes.h" +#include "net.minecraft.world.entity.monster.h" +#include "net.minecraft.world.level.h" +#include "net.minecraft.world.level.tile.h" +#include "net.minecraft.world.phys.h" +#include "Bat.h" + +Bat::Bat(Level *level) : AmbientCreature(level) +{ + // 4J Stu - This function call had to be moved here from the Entity ctor to ensure that + // the derived version of the function is called + this->defineSynchedData(); + registerAttributes(); + setHealth(getMaxHealth()); + + targetPosition = NULL; + + setSize(.5f, .9f); + setResting(true); +} + +void Bat::defineSynchedData() +{ + AmbientCreature::defineSynchedData(); + + entityData->define(DATA_ID_FLAGS, (char) 0); +} + +float Bat::getSoundVolume() +{ + return 0.1f; +} + +float Bat::getVoicePitch() +{ + return AmbientCreature::getVoicePitch() * .95f; +} + +int Bat::getAmbientSound() +{ + if (isResting() && random->nextInt(4) != 0) + { + return -1; + } + return eSoundType_MOB_BAT_IDLE; //"mob.bat.idle"; +} + +int Bat::getHurtSound() +{ + return eSoundType_MOB_BAT_HURT; //"mob.bat.hurt"; +} + +int Bat::getDeathSound() +{ + return eSoundType_MOB_BAT_DEATH; //"mob.bat.death"; +} + +bool Bat::isPushable() +{ + // bats can't be pushed by other mobs + return false; +} + +void Bat::doPush(shared_ptr<Entity> e) +{ + // bats don't push other mobs +} + +void Bat::pushEntities() +{ + // bats don't push other mobs +} + +void Bat::registerAttributes() +{ + AmbientCreature::registerAttributes(); + + getAttribute(SharedMonsterAttributes::MAX_HEALTH)->setBaseValue(6); +} + +bool Bat::isResting() +{ + return (entityData->getByte(DATA_ID_FLAGS) & FLAG_RESTING) != 0; +} + +void Bat::setResting(bool value) +{ + char current = entityData->getByte(DATA_ID_FLAGS); + if (value) + { + entityData->set(DATA_ID_FLAGS, (char) (current | FLAG_RESTING)); + } + else + { + entityData->set(DATA_ID_FLAGS, (char) (current & ~FLAG_RESTING)); + } +} + +bool Bat::useNewAi() +{ + return true; +} + +void Bat::tick() +{ + + AmbientCreature::tick(); + + if (isResting()) + { + xd = yd = zd = 0; + y = Mth::floor(y) + 1.0 - bbHeight; + } + else + { + yd *= .6f; + } + +} + +inline int signum(double x) { return (x > 0) - (x < 0); } + +void Bat::newServerAiStep() +{ + AmbientCreature::newServerAiStep(); + + if (isResting()) + { + if (!level->isSolidBlockingTile(Mth::floor(x), (int) y + 1, Mth::floor(z))) + { + setResting(false); + level->levelEvent(nullptr, LevelEvent::SOUND_BAT_LIFTOFF, (int) x, (int) y, (int) z, 0); + } + else + { + + if (random->nextInt(200) == 0) + { + yHeadRot = random->nextInt(360); + } + + if (level->getNearestPlayer(shared_from_this(), 4.0f) != NULL) + { + setResting(false); + level->levelEvent(nullptr, LevelEvent::SOUND_BAT_LIFTOFF, (int) x, (int) y, (int) z, 0); + } + } + } + else + { + + if (targetPosition != NULL && (!level->isEmptyTile(targetPosition->x, targetPosition->y, targetPosition->z) || targetPosition->y < 1)) + { + delete targetPosition; + targetPosition = NULL; + } + if (targetPosition == NULL || random->nextInt(30) == 0 || targetPosition->distSqr((int) x, (int) y, (int) z) < 4) + { + delete targetPosition; + targetPosition = new Pos((int) x + random->nextInt(7) - random->nextInt(7), (int) y + random->nextInt(6) - 2, (int) z + random->nextInt(7) - random->nextInt(7)); + } + + double dx = (targetPosition->x + .5) - x; + double dy = (targetPosition->y + .1) - y; + double dz = (targetPosition->z + .5) - z; + + xd = xd + (signum(dx) * .5f - xd) * .1f; + yd = yd + (signum(dy) * .7f - yd) * .1f; + zd = zd + (signum(dz) * .5f - zd) * .1f; + + float yRotD = (float) (atan2(zd, xd) * 180 / PI) - 90; + float rotDiff = Mth::wrapDegrees(yRotD - yRot); + yya = .5f; + yRot += rotDiff; + + if (random->nextInt(100) == 0 && level->isSolidBlockingTile(Mth::floor(x), (int) y + 1, Mth::floor(z))) + { + setResting(true); + } + + } +} + +bool Bat::makeStepSound() +{ + return false; +} + +void Bat::causeFallDamage(float distance) +{ +} + +void Bat::checkFallDamage(double ya, bool onGround) +{ + // this method is empty because flying creatures should + // not trigger the "fallOn" tile calls (such as trampling crops) +} + +bool Bat::isIgnoringTileTriggers() +{ + return true; +} + +bool Bat::hurt(DamageSource *source, float dmg) +{ + if (isInvulnerable()) return false; + if (!level->isClientSide) + { + if (isResting()) + { + setResting(false); + } + } + + return AmbientCreature::hurt(source, dmg); +} + +void Bat::readAdditionalSaveData(CompoundTag *tag) +{ + AmbientCreature::readAdditionalSaveData(tag); + + entityData->set(DATA_ID_FLAGS, tag->getByte(L"BatFlags")); +} + +void Bat::addAdditonalSaveData(CompoundTag *entityTag) +{ + AmbientCreature::addAdditonalSaveData(entityTag); + + entityTag->putByte(L"BatFlags", entityData->getByte(DATA_ID_FLAGS)); +} + + +bool Bat::canSpawn() +{ + int yt = Mth::floor(bb->y0); + if (yt >= level->seaLevel) return false; + + int xt = Mth::floor(x); + int zt = Mth::floor(z); + + int br = level->getRawBrightness(xt, yt, zt); + int maxLight = 4; + + if ((Calendar::GetDayOfMonth() + 1 == 10 && Calendar::GetDayOfMonth() >= 20) || (Calendar::GetMonth() + 1 == 11 && Calendar::GetMonth() <= 3)) + { + maxLight = 7; + } + else if (random->nextBoolean()) + { + return false; + } + + if (br > random->nextInt(maxLight)) return false; + + return AmbientCreature::canSpawn(); +}
\ No newline at end of file |
