diff options
Diffstat (limited to 'Minecraft.World/Ghast.cpp')
| -rw-r--r-- | Minecraft.World/Ghast.cpp | 249 |
1 files changed, 249 insertions, 0 deletions
diff --git a/Minecraft.World/Ghast.cpp b/Minecraft.World/Ghast.cpp new file mode 100644 index 00000000..fcf0b705 --- /dev/null +++ b/Minecraft.World/Ghast.cpp @@ -0,0 +1,249 @@ +#include "stdafx.h" +#include "net.minecraft.world.h" +#include "net.minecraft.world.phys.h" +#include "net.minecraft.world.level.h" +#include "net.minecraft.world.entity.h" +#include "net.minecraft.world.entity.projectile.h" +#include "net.minecraft.world.entity.player.h" +#include "net.minecraft.world.item.h" +#include "net.minecraft.world.damagesource.h" +#include "net.minecraft.stats.h" +#include "Ghast.h" +#include "..\Minecraft.Client\Textures.h" +#include "LevelEvent.h" +#include "SoundTypes.h" + + + +void Ghast::_init() +{ + floatDuration = 0; + target = nullptr; + retargetTime = 0; + oCharge = 0; + charge = 0; + + xTarget = 0.0f; + yTarget = 0.0f; + zTarget = 0.0f; +} + +Ghast::Ghast(Level *level) : FlyingMob( 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(); + + // 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 + health = getMaxHealth(); + + _init(); + + this->textureIdx = TN_MOB_GHAST; // 4J was L"/mob/ghast.png"; + this->setSize(4, 4); + this->fireImmune = true; + xpReward = Enemy::XP_REWARD_MEDIUM; +} + +bool Ghast::hurt(DamageSource *source, int dmg) +{ + if (source->getMsgId() == ChatPacket::e_ChatDeathFireball) + { + shared_ptr<Player> player = dynamic_pointer_cast<Player>( source->getEntity() ); + if (player != NULL) + { + // reflected fireball, kill the ghast + FlyingMob::hurt(source, 1000); + player->awardStat(GenericStats::ghast(),GenericStats::param_ghast()); + return true; + } + } + + return FlyingMob::hurt(source, dmg); +} + +void Ghast::defineSynchedData() +{ + FlyingMob::defineSynchedData(); + + entityData->define(DATA_IS_CHARGING, (byte) 0); +} + +int Ghast::getMaxHealth() +{ + return 10; +} + +void Ghast::tick() +{ + FlyingMob::tick(); + byte current = entityData->getByte(DATA_IS_CHARGING); +// this->textureName = current == 1 ? L"/mob/ghast_fire.png" : L"/mob/ghast.png"; // 4J replaced with following line + this->textureIdx = current == 1 ? TN_MOB_GHAST_FIRE : TN_MOB_GHAST; +} + +void Ghast::serverAiStep() +{ + if (!level->isClientSide && level->difficulty == Difficulty::PEACEFUL) remove(); + checkDespawn(); + + oCharge = charge; + double xd = xTarget - x; + double yd = yTarget - y; + double zd = zTarget - z; + + double dd = xd * xd + yd * yd + zd * zd; + + if (dd < 1 * 1 || dd > 60 * 60) + { + xTarget = x + (random->nextFloat() * 2 - 1) * 16; + yTarget = y + (random->nextFloat() * 2 - 1) * 16; + zTarget = z + (random->nextFloat() * 2 - 1) * 16; + } + + if (floatDuration-- <= 0) + { + floatDuration += random->nextInt(5) + 2; + + dd = sqrt(dd); + + if (canReach(xTarget, yTarget, zTarget, dd)) + { + this->xd += xd / dd * 0.1; + this->yd += yd / dd * 0.1; + this->zd += zd / dd * 0.1; + } + else + { + xTarget = x; + yTarget = y; + zTarget = z; + } + } + + if (target != NULL && target->removed) target = nullptr; + if (target == NULL || retargetTime-- <= 0) + { + target = level->getNearestAttackablePlayer(shared_from_this(), 100); + if (target != NULL) + { + retargetTime = 20; + } + } + + double maxDist = 64.0f; + if (target != NULL && target->distanceToSqr(shared_from_this()) < maxDist * maxDist) + { + double xdd = target->x - x; + double ydd = (target->bb->y0 + target->bbHeight / 2) - (y + bbHeight / 2); + double zdd = target->z - z; + yBodyRot = yRot = -(float) atan2(xdd, zdd) * 180 / PI; + + if (this->canSee(target)) + { + if (charge == 10) + { + // 4J - change brought forward from 1.2.3 + level->levelEvent(nullptr, LevelEvent::SOUND_GHAST_WARNING, (int) x, (int) y, (int) z, 0); + } + charge++; + if (charge == 20) + { + // 4J - change brought forward from 1.2.3 + level->levelEvent(nullptr, LevelEvent::SOUND_GHAST_FIREBALL, (int) x, (int) y, (int) z, 0); + shared_ptr<Fireball> ie = shared_ptr<Fireball>( new Fireball(level, dynamic_pointer_cast<Mob>( shared_from_this() ), xdd, ydd, zdd) ); + double d = 4; + Vec3 *v = getViewVector(1); + ie->x = x + v->x * d; + ie->y = y + bbHeight / 2 + 0.5f; + ie->z = z + v->z * d; + level->addEntity(ie); + charge = -40; + } + } + else + { + if (charge > 0) charge--; + } + } + else + { + yBodyRot = yRot = -(float) atan2(this->xd, this->zd) * 180 / PI; + if (charge > 0) charge--; + } + + if (!level->isClientSide) + { + byte old = entityData->getByte(DATA_IS_CHARGING); + byte current = (byte) (charge > 10 ? 1 : 0); + if (old != current) + { + entityData->set(DATA_IS_CHARGING, current); + } + } +} + +bool Ghast::canReach(double xt, double yt, double zt, double dist) +{ + double xd = (xTarget - x) / dist; + double yd = (yTarget - y) / dist; + double zd = (zTarget - z) / dist; + + AABB *bb = this->bb->copy(); + for (int d = 1; d < dist; d++) + { + bb->move(xd, yd, zd); + if (!level->getCubes( shared_from_this(), bb)->empty()) return false; + } + + return true; +} + +int Ghast::getAmbientSound() +{ + return eSoundType_MOB_GHAST_MOAN; +} + +int Ghast::getHurtSound() +{ + return eSoundType_MOB_GHAST_SCREAM; +} + +int Ghast::getDeathSound() +{ + return eSoundType_MOB_GHAST_DEATH; +} + +int Ghast::getDeathLoot() +{ + return Item::sulphur->id; +} + +void Ghast::dropDeathLoot(bool wasKilledByPlayer, int playerBonusLevel) +{ + int count = random->nextInt(2) + random->nextInt(1 + playerBonusLevel); + for (int i = 0; i < count; i++) + { + spawnAtLocation(Item::ghastTear_Id, 1); + } + count = random->nextInt(3) + random->nextInt(1 + playerBonusLevel); + for (int i = 0; i < count; i++) + { + spawnAtLocation(Item::sulphur_Id, 1); + } +} + +float Ghast::getSoundVolume() +{ + return 0.4f;//10; 4J-PB - changing due to customer demands +} + +bool Ghast::canSpawn() +{ + return (random->nextInt(20) == 0 && FlyingMob::canSpawn() && level->difficulty > Difficulty::PEACEFUL); +} + +int Ghast::getMaxSpawnClusterSize() +{ + return 1; +} |
