herobrine removed

This commit is contained in:
Lord_Cambion 2026-04-02 14:45:46 +02:00
parent a552afded7
commit e5a8abd2ac
45 changed files with 18 additions and 871 deletions

View file

@ -230,12 +230,7 @@ const WCHAR *ConsoleSoundEngine::wchSoundNames[eSoundType_MAX]=
L"mob.rabbit.hop",
L"mob.phantom.bite", // eSoundType_MOB_PHANTOM_BITE
L"mob.phantom.death", // eSoundType_MOB_PHANTOM_DEATH
L"mob.phantom.flap", // eSoundType_MOB_PHANTOM_FLAP
L"mob.phantom.hurt", // eSoundType_MOB_PHANTOM_HURT
L"mob.phantom.idle", // eSoundType_MOB_PHANTOM_IDLE
L"mob.phantom.swoop", // eSoundType_MOB_PHANTOM_SWOOP
};

View file

@ -8559,8 +8559,7 @@ wstring CMinecraftApp::getEntityName(eINSTANCEOF type)
return app.GetString(IDS_BAT);
case eTYPE_RABBIT:
return app.GetString(IDS_RABBIT);
case eTYPE_PHANTOM:
return L"Phantom";
};
return L"";

Binary file not shown.

Before

Width:  |  Height:  |  Size: 639 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 112 B

View file

@ -82,7 +82,7 @@
#include "BatRenderer.h"
#include "CaveSpiderRenderer.h"
#include "RabbitRenderer.h"
#include "PhantomRenderer.h"
#include "ArmorStandRenderer.h"
#include "EndermiteRenderer.h"
#include "MobRenderer.h"
@ -137,7 +137,7 @@ EntityRenderDispatcher::EntityRenderDispatcher()
renderers[eTYPE_WITHERBOSS] = new WitherBossRenderer();
renderers[eTYPE_RABBIT] = new RabbitRenderer();
renderers[eTYPE_PHANTOM] = new PhantomRenderer();
renderers[eTYPE_ENTITY] = new DefaultRenderer();
renderers[eTYPE_PAINTING] = new PaintingRenderer();

View file

@ -1,134 +0,0 @@
#include "stdafx.h"
#include "..\Minecraft.World\net.minecraft.world.entity.monster.h"
#include "PhantomModel.h"
#include "ModelPart.h"
#include "../Minecraft.World/Phantom.h"
PhantomModel::PhantomModel() : Model()
{
texWidth = 64;
texHeight = 64;
body = new ModelPart(this, 0, 8);
body->addBox(-3.0f, -2.0f, -8.0f, 5, 3, 9);
head = new ModelPart(this, 0, 0);
head->addBox(-4.0f, -2.0f, -5.0f, 7, 3, 5);
leftWing = new ModelPart(this, 23, 12);
leftWing->addBox(0.0f, 0.0f, 0.0f, 6, 2, 9);
leftWingTip = new ModelPart(this, 16, 24);
leftWingTip->addBox(0.0f, 0.0f, 0.0f, 13, 1, 9);
rightWing = new ModelPart(this, 23, 12);
rightWing->bMirror = true;
rightWing->addBox(-6.0f, 0.0f, 0.0f, 6, 2, 9);
rightWingTip = new ModelPart(this, 16, 24);
rightWingTip->bMirror = true;
rightWingTip->addBox(-13.0f, 0.0f, 0.0f, 13, 1, 9);
tailBase = new ModelPart(this, 3, 20);
tailBase->addBox(-2.0f, 0.0f, 0.0f, 3, 2, 6);
tailTip = new ModelPart(this, 4, 29);
tailTip->addBox(-1.0f, 0.0f, 0.0f, 1, 1, 6);
body->addChild(head);
body->addChild(leftWing);
body->addChild(rightWing);
body->addChild(tailBase);
leftWing->addChild(leftWingTip);
rightWing->addChild(rightWingTip);
tailBase->addChild(tailTip);
const float s = 1.0f / 16.0f;
body->compile(s);
head->compile(s);
leftWing->compile(s);
rightWing->compile(s);
leftWingTip->compile(s);
rightWingTip->compile(s);
tailBase->compile(s);
tailTip->compile(s);
}
int PhantomModel::modelVersion()
{
return 3;
}
void PhantomModel::render(shared_ptr<Entity> entity,
float time, float r, float bob,
float yRot, float xRot,
float scale, bool usecompiled)
{
shared_ptr<Phantom> phantom = dynamic_pointer_cast<Phantom>(entity);
if (!phantom) return;
float flapTime = (float)phantom->tickCount;
const float rad = (float)(PI / 180.0);
float f = flapTime * 7.448451f * rad;
body->xRot = -0.1f;
body->yRot = 0.0f;
body->zRot = 0.0f;
body->setPos(0.0f, 0.0f, 0.0f);
head->xRot = 0.2f;
head->yRot = 0.0f;
head->zRot = 0.0f;
head->setPos(0.0f, 1.0f, -7.0f);
leftWing->setPos(2.0f, -2.0f, -8.0f);
leftWing->xRot = 0.0f;
leftWing->yRot = 0.0f;
leftWing->zRot = 0.1f;
rightWing->setPos(-3.0f, -2.0f, -8.0f);
rightWing->xRot = 0.0f;
rightWing->yRot = 0.0f;
rightWing->zRot = -0.1f;
leftWingTip->setPos(6.0f, 0.0f, 0.0f);
leftWingTip->zRot = 0.1f;
rightWingTip->setPos(-6.0f, 0.0f, 0.0f);
rightWingTip->zRot = -0.1f;
tailBase->setPos(0.0f, -2.0f, 1.0f);
tailTip->setPos(0.0f, 0.5f, 6.0f);
float flapAngle = cos(f) * 16.0f * rad;
leftWing->zRot += flapAngle;
leftWingTip->zRot += flapAngle;
rightWing->zRot -= flapAngle;
rightWingTip->zRot -= flapAngle;
float tailAngle = -(5.0f + cos(f * 2.0f) * 5.0f) * rad;
tailBase->xRot = tailAngle;
tailTip->xRot = tailAngle;
body->render(scale, usecompiled);
}

View file

@ -1,23 +0,0 @@
#pragma once
#include "Model.h"
class PhantomModel : public Model
{
private:
ModelPart *body;
ModelPart *head;
ModelPart *leftWing;
ModelPart *leftWingTip;
ModelPart *rightWing;
ModelPart *rightWingTip;
ModelPart *tailBase;
ModelPart *tailTip;
public:
PhantomModel();
int modelVersion();
virtual void render(shared_ptr<Entity> entity,
float time, float r, float bob,
float yRot, float xRot,
float scale, bool usecompiled);
};

View file

@ -1,108 +0,0 @@
#include "stdafx.h"
#include "..\Minecraft.World\net.minecraft.world.entity.monster.h"
#include "PhantomRenderer.h"
#include "PhantomModel.h"
#include "../Minecraft.World/Phantom.h"
#include "Textures.h"
ResourceLocation PhantomRenderer::PHANTOM_LOCATION = ResourceLocation(TN_MOB_PHANTOM);
ResourceLocation PhantomRenderer::PHANTOM_EYES_LOCATION = ResourceLocation(TN_MOB_PHANTOM_EYES);
PhantomRenderer::PhantomRenderer() : MobRenderer(new PhantomModel(), 0.5f)
{
modelVersion = static_cast<PhantomModel *>(model)->modelVersion();
this->setArmor(model);
}
void PhantomRenderer::render(shared_ptr<Entity> _mob,
double x, double y, double z,
float rot, float a)
{
int currentVersion = static_cast<PhantomModel *>(model)->modelVersion();
if (currentVersion != modelVersion)
{
modelVersion = currentVersion;
model = new PhantomModel();
this->setArmor(model);
}
MobRenderer::render(_mob, x, y, z, rot, a);
}
ResourceLocation *PhantomRenderer::getTextureLocation(shared_ptr<Entity> mob)
{
return &PHANTOM_LOCATION;
}
void PhantomRenderer::scale(shared_ptr<LivingEntity> mob, float a)
{
shared_ptr<Phantom> phantom = dynamic_pointer_cast<Phantom>(mob);
if (phantom)
{
float s = 1.0f + 0.15f * phantom->getPhantomSize();
glScalef(s, s, s);
}
//glScalef(0.35f, 0.35f, 0.35f);
}
void PhantomRenderer::setupPosition(shared_ptr<LivingEntity> mob,
double x, double y, double z)
{
MobRenderer::setupPosition(mob, x, y-0.5, z );
}
void PhantomRenderer::setupRotations(shared_ptr<LivingEntity> _mob,
float bob, float bodyRot, float a)
{
glTranslatef(0.0f, -0.5f, 0.0f);
glTranslatef(0.0f, cos(bob * 0.3f) * 0.1f, 0.0f);
MobRenderer::setupRotations(_mob, bob, bodyRot, a);
}
int PhantomRenderer::prepareArmor(shared_ptr<LivingEntity> _mob, int layer, float a)
{
shared_ptr<Phantom> mob = dynamic_pointer_cast<Phantom>(_mob);
if (layer != 0) return -1;
bindTexture(&PHANTOM_EYES_LOCATION);
float br = 1;
glEnable(GL_BLEND);
#ifdef _XBOX
glDisable(GL_ALPHA_TEST);
#endif
glBlendFunc(GL_ONE, GL_ONE);
glDisable(GL_LIGHTING);
if (mob->isInvisible())
{
glDepthMask(false);
}
else
{
glDepthMask(true);
}
if (SharedConstants::TEXTURE_LIGHTING)
{
int col = 0xf0f0;
int u = col % 65536;
int v = col / 65536;
glMultiTexCoord2f(GL_TEXTURE1, u / 1.0f, v / 1.0f);
glColor4f(1, 1, 1, 1);
}
glEnable(GL_LIGHTING);
glColor4f(1, 1, 1, br);
return 1;
}

View file

@ -1,27 +0,0 @@
#pragma once
#include "MobRenderer.h"
class PhantomModel;
class PhantomRenderer : public MobRenderer
{
static ResourceLocation PHANTOM_LOCATION;
static ResourceLocation PHANTOM_EYES_LOCATION;
int modelVersion;
public:
PhantomRenderer();
virtual void render(shared_ptr<Entity> mob,
double x, double y, double z,
float rot, float a);
protected:
virtual ResourceLocation *getTextureLocation(shared_ptr<Entity> mob);
virtual void scale(shared_ptr<LivingEntity> mob, float a);
virtual void setupPosition(shared_ptr<LivingEntity> mob,
double x, double y, double z);
virtual void setupRotations(shared_ptr<LivingEntity> mob,
float bob, float bodyRot, float a);
virtual int prepareArmor(shared_ptr<LivingEntity> mob, int layer, float a);
};

View file

@ -175,8 +175,7 @@ const wchar_t *Textures::preLoaded[TN_COUNT] =
L"mob/rabbit/white_splotched",
L"mob/rabbit/toast",
L"mob/rabbit/caerbannog",
L"mob/phantom",
L"mob/phantom_eyes",
L"item/trapped",

View file

@ -165,8 +165,7 @@ typedef enum _TEXTURE_NAME
TN_MOB_RABBIT_WHITE_SPLOTCHED,
TN_MOB_RABBIT_TOAST,
TN_MOB_RABBIT_CAERBANNOG,
TN_MOB_PHANTOM,
TN_MOB_PHANTOM_EYES,
TN_TILE_TRAP_CHEST,
TN_TILE_LARGE_TRAP_CHEST,

View file

@ -618,8 +618,7 @@ set(_MINECRAFT_CLIENT_COMMON_NET_MINECRAFT_CLIENT_MODEL
"${CMAKE_CURRENT_SOURCE_DIR}/ArmorStandModel.h"
"${CMAKE_CURRENT_SOURCE_DIR}/EndermiteModel.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/EndermiteModel.h"
"${CMAKE_CURRENT_SOURCE_DIR}/PhantomModel.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/PhantomModel.h"
)
source_group("net/minecraft/client/model" FILES ${_MINECRAFT_CLIENT_COMMON_NET_MINECRAFT_CLIENT_MODEL})
@ -893,8 +892,7 @@ set(_MINECRAFT_CLIENT_COMMON_NET_MINECRAFT_CLIENT_RENDERER_ENTITY
"${CMAKE_CURRENT_SOURCE_DIR}/ZombieRenderer.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/ZombieRenderer.h"
"${CMAKE_CURRENT_SOURCE_DIR}/RabbitRenderer.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/PhantomRenderer.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/PhantomRenderer.h"
"${CMAKE_CURRENT_SOURCE_DIR}/RabbitRenderer.h"
"${CMAKE_CURRENT_SOURCE_DIR}/ArmorStandRenderer.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/EndermiteRenderer.cpp"
)

View file

@ -390,8 +390,6 @@ set(_MINECRAFT_SERVER_COMMON_ROOT
"${CMAKE_CURRENT_SOURCE_DIR}/../Minecraft.Client/QuadrupedModel.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/../Minecraft.Client/RabbitModel.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/../Minecraft.Client/RabbitRenderer.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/../Minecraft.Client/PhantomModel.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/../Minecraft.Client/PhantomRenderer.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/../Minecraft.Client/Rect2i.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/../Minecraft.Client/RedDustParticle.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/../Minecraft.Client/RemotePlayer.cpp"

View file

@ -164,7 +164,7 @@ Biome::Biome(int id) : id(id)
enemies.push_back(new MobSpawnerData(eTYPE_SLIME, 10, 4, 4));
enemies.push_back(new MobSpawnerData(eTYPE_ENDERMAN, 1, 1, 4));
enemies.push_back(new MobSpawnerData(eTYPE_WITCH, 1, 1, 1));
enemies.push_back(new MobSpawnerData(eTYPE_PHANTOM, 5, 1, 2));
waterFriendlies.push_back(new MobSpawnerData(eTYPE_SQUID, 10, 4, 4));
ambientFriendlies.push_back(new MobSpawnerData(eTYPE_BAT, 10, 8, 8));

View file

@ -11,7 +11,7 @@ set(MINECRAFT_WORLD_SOURCES
${SOURCES_COMMON}
)
add_library(Minecraft.World STATIC ${MINECRAFT_WORLD_SOURCES} "IceSpikeFeature.cpp" "IceSpikeFeature.h" "BlockBlobFeature.h" "BlockBlobFeature.cpp" "Phantom.h" "Phantom.cpp")
add_library(Minecraft.World STATIC ${MINECRAFT_WORLD_SOURCES})
target_include_directories(Minecraft.World
PRIVATE

View file

@ -168,7 +168,7 @@ enum eINSTANCEOF
eTYPE_BLAZE = eTYPE_MONSTER | eTYPE_VALID_IN_SPAWNER_FLAG | 0x6,
eTYPE_WITCH = eTYPE_MONSTER | eTYPE_VALID_IN_SPAWNER_FLAG | 0x7,
eTYPE_WITHERBOSS = eTYPE_MONSTER | eTYPE_VALID_IN_SPAWNER_FLAG | 0x8,
eTYPE_PHANTOM = eTYPE_MONSTER | eTYPE_VALID_IN_SPAWNER_FLAG | 0x9,
eTYPE_ENDERMITE = eTYPE_MONSTER | eTYPE_VALID_IN_SPAWNER_FLAG | 0x10,

View file

@ -95,7 +95,7 @@ void EntityIO::staticCtor()
setId(WitherBoss::create, eTYPE_WITHERBOSS, L"WitherBoss", 64);
setId(Bat::create, eTYPE_BAT, L"Bat", 65, eMinecraftColour_Mob_Bat_Colour1, eMinecraftColour_Mob_Bat_Colour2, IDS_BAT);
setId(Witch::create, eTYPE_WITCH, L"Witch", 66, eMinecraftColour_Mob_Witch_Colour1, eMinecraftColour_Mob_Witch_Colour2, IDS_WITCH);
setId(Phantom::create, eTYPE_PHANTOM, L"Phantom", 254, eMinecraftColour_Mob_Ghast_Colour1, eMinecraftColour_Mob_Ghast_Colour2, IDS_ZOMBIE);
setId(Pig::create, eTYPE_PIG, L"Pig", 90, eMinecraftColour_Mob_Pig_Colour1, eMinecraftColour_Mob_Pig_Colour2, IDS_PIG);
setId(Sheep::create, eTYPE_SHEEP, L"Sheep", 91, eMinecraftColour_Mob_Sheep_Colour1, eMinecraftColour_Mob_Sheep_Colour2, IDS_SHEEP);

View file

@ -1,462 +0,0 @@
#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.ai.attributes.h"
#include "net.minecraft.world.entity.ai.control.h"
#include "net.minecraft.world.entity.ai.goal.h"
#include "net.minecraft.world.entity.ai.goal.target.h"
#include "net.minecraft.world.entity.monster.h"
#include "net.minecraft.world.entity.player.h"
#include "net.minecraft.world.damagesource.h"
#include "net.minecraft.world.level.tile.h"
#include "LevelEvent.h"
#include "SoundTypes.h"
#include "Phantom.h"
class PhantomMoveControl : public MoveControl {
Phantom* phantom;
public:
PhantomMoveControl(Phantom* p) : MoveControl(p), phantom(p) {}
void tick() override {
if (phantom->horizontalCollision) {
phantom->yRot += 180.0f;
phantom->flySpeed = 0.1f;
}
double d0 = phantom->moveTargetX - phantom->x;
double d1 = phantom->moveTargetY - phantom->y;
double d2 = phantom->moveTargetZ - phantom->z;
double d3 = sqrt(d0 * d0 + d2 * d2);
if (abs(d3) > 1.0e-5) {
double d4 = 1.0 - abs(d1 * 0.7) / d3;
d0 *= d4;
d2 *= d4;
d3 = sqrt(d0 * d0 + d2 * d2);
double d5 = sqrt(d0 * d0 + d2 * d2 + d1 * d1);
float f1 = (float)(atan2(d2, d0) * 180.0 / PI);
float f2 = Mth::wrapDegrees(phantom->yRot + 90.0f);
float f3 = Mth::wrapDegrees(f1);
float diff = Mth::wrapDegrees(f3 - f2);
phantom->yRot = f2 + Mth::clamp(diff, -4.0f, 4.0f) - 90.0f;
phantom->yBodyRot = phantom->yRot;
if (abs(diff) < 3.0f) {
phantom->flySpeed += Mth::clamp(1.8f - phantom->flySpeed, -0.005f * (1.8f / max(phantom->flySpeed, 0.001f)), 0.005f * (1.8f / max(phantom->flySpeed, 0.001f)));
} else {
phantom->flySpeed += Mth::clamp(0.2f - phantom->flySpeed, -0.025f, 0.025f);
}
float f4 = (float)(-(atan2(-d1, d3) * 180.0 / PI));
phantom->xRot = f4;
float f5_rad = (phantom->yRot + 90.0f) * (float)(PI / 180.0);
float f4_rad = f4 * (float)(PI / 180.0);
double d6 = phantom->flySpeed * cos(f5_rad) * abs(d0 / d5);
double d7 = phantom->flySpeed * sin(f5_rad) * abs(d2 / d5);
double d8 = phantom->flySpeed * sin(f4_rad) * abs(d1 / d5);
phantom->xd += (d6 - phantom->xd) * 0.2;
phantom->yd += (d8 - phantom->yd) * 0.2;
phantom->zd += (d7 - phantom->zd) * 0.2;
}
}
};
class PhantomAttackStrategyGoal : public Goal {
Phantom* phantom;
int nextSweepTick;
public:
PhantomAttackStrategyGoal(Phantom* p) : phantom(p), nextSweepTick(0) {}
bool canUse() override {
shared_ptr<LivingEntity> target = phantom->getTarget();
return target != nullptr && target->isAlive();
}
void start() override {
nextSweepTick = 10 * 20; // About 10 seconds
phantom->attackPhase = Phantom::AttackPhase::CIRCLE;
setAnchorAboveTarget();
}
void stop() override {
if (phantom->hasAnchor) {
phantom->anchorY = phantom->level->getTopSolidBlock(phantom->anchorX, phantom->anchorZ) + 10 + phantom->random->nextInt(20);
}
}
void tick() override {
if (phantom->attackPhase == Phantom::AttackPhase::CIRCLE) {
nextSweepTick--;
if (nextSweepTick <= 0) {
phantom->attackPhase = Phantom::AttackPhase::SWOOP;
setAnchorAboveTarget();
nextSweepTick = (8 + phantom->random->nextInt(4)) * 20;
phantom->level->levelEvent(nullptr, LevelEvent::SOUND_BAT_LIFTOFF, (int)phantom->x, (int)phantom->y, (int)phantom->z, 0);
}
}
}
private:
void setAnchorAboveTarget() {
shared_ptr<LivingEntity> target = phantom->getTarget();
if (target != nullptr) {
phantom->anchorX = Mth::floor(target->x);
phantom->anchorY = Mth::floor(target->y) + 20 + phantom->random->nextInt(20);
phantom->anchorZ = Mth::floor(target->z);
if (phantom->anchorY < phantom->level->seaLevel) {
phantom->anchorY = phantom->level->seaLevel + 1;
}
phantom->hasAnchor = true;
}
}
};
class PhantomSweepAttackGoal : public Goal {
Phantom* phantom;
public:
PhantomSweepAttackGoal(Phantom* p) : phantom(p) {}
bool canUse() override {
return phantom->getTarget() != nullptr && phantom->attackPhase == Phantom::AttackPhase::SWOOP;
}
bool canContinueToUse() override {
shared_ptr<LivingEntity> target = phantom->getTarget();
if (target == nullptr || !target->isAlive()) return false;
return canUse();
}
void stop() override {
phantom->setTarget(nullptr);
phantom->attackPhase = Phantom::AttackPhase::CIRCLE;
}
void tick() override {
shared_ptr<LivingEntity> target = phantom->getTarget();
if (target != nullptr) {
phantom->moveTargetX = target->x;
phantom->moveTargetY = target->y + (target->bbHeight * 0.5);
phantom->moveTargetZ = target->z;
// Hit control
double dx = phantom->x - target->x;
double dy = phantom->y - target->y;
double dz = phantom->z - target->z;
if (sqrt(dx*dx + dy*dy + dz*dz) < 2.0) { // Close range
phantom->doHurtTarget(target);
phantom->playSound(eSoundType_MOB_PHANTOM_BITE, 1.0f, 1.0f);
phantom->attackPhase = Phantom::AttackPhase::CIRCLE;
phantom->level->levelEvent(nullptr, LevelEvent::SOUND_BAT_LIFTOFF, (int)phantom->x, (int)phantom->y, (int)phantom->z, 0);
} else if (phantom->horizontalCollision || phantom->hurtTime > 0) {
phantom->attackPhase = Phantom::AttackPhase::CIRCLE;
}
}
}
};
class PhantomCircleAroundAnchorGoal : public Goal {
Phantom* phantom;
public:
PhantomCircleAroundAnchorGoal(Phantom* p) : phantom(p) {}
bool canUse() override {
return phantom->getTarget() == nullptr || phantom->attackPhase == Phantom::AttackPhase::CIRCLE;
}
void start() override {
phantom->circleDistance = 5.0f + phantom->random->nextFloat() * 10.0f;
phantom->circleHeight = -4.0f + phantom->random->nextFloat() * 9.0f;
phantom->circleClockwise = phantom->random->nextBoolean() ? 1.0f : -1.0f;
selectNext();
}
void tick() override {
if (phantom->random->nextInt(350) == 0) phantom->circleHeight = -4.0f + phantom->random->nextFloat() * 9.0f;
if (phantom->random->nextInt(250) == 0) {
phantom->circleDistance++;
if (phantom->circleDistance > 15.0f) {
phantom->circleDistance = 5.0f;
phantom->circleClockwise = -phantom->circleClockwise;
}
}
if (phantom->random->nextInt(450) == 0) {
phantom->circleAngle = phantom->random->nextFloat() * 2.0f * (float)PI;
selectNext();
}
if (phantom->isTouchingMoveTarget()) selectNext();
// Height control to avoid crashing
if (phantom->moveTargetY < phantom->y && !phantom->level->isEmptyTile(Mth::floor(phantom->x), Mth::floor(phantom->y) - 1, Mth::floor(phantom->z))) {
phantom->circleHeight = max(1.0f, phantom->circleHeight);
selectNext();
}
if (phantom->moveTargetY > phantom->y && !phantom->level->isEmptyTile(Mth::floor(phantom->x), Mth::floor(phantom->y) + 1, Mth::floor(phantom->z))) {
phantom->circleHeight = min(-1.0f, phantom->circleHeight);
selectNext();
}
}
private:
void selectNext() {
if (!phantom->hasAnchor) {
phantom->anchorX = Mth::floor(phantom->x);
phantom->anchorY = Mth::floor(phantom->y);
phantom->anchorZ = Mth::floor(phantom->z);
phantom->hasAnchor = true;
}
phantom->circleAngle += phantom->circleClockwise * 15.0f * (float)(PI / 180.0);
phantom->moveTargetX = phantom->anchorX + 0.5 + phantom->circleDistance * cos(phantom->circleAngle);
phantom->moveTargetY = phantom->anchorY - 4.0 + phantom->circleHeight;
phantom->moveTargetZ = phantom->anchorZ + 0.5 + phantom->circleDistance * sin(phantom->circleAngle);
phantom->moveTargetInitialized = true;
}
};
class PhantomAttackPlayerTargetGoal : public Goal {
Phantom* phantom;
int nextScanTick;
public:
PhantomAttackPlayerTargetGoal(Phantom* p) : phantom(p), nextScanTick(20) {}
bool canUse() override {
if (nextScanTick > 0) {
nextScanTick--;
return false;
}
nextScanTick = 60;
shared_ptr<Player> player = phantom->level->getNearestAttackablePlayer(phantom->shared_from_this(), 64.0);
if (player != nullptr) {
phantom->setTarget(player);
return true;
}
return false;
}
bool canContinueToUse() override {
shared_ptr<LivingEntity> target = phantom->getTarget();
return target != nullptr && target->isAlive();
}
};
Phantom::Phantom(Level *level) : FlyingMob(level)
{
this->defineSynchedData();
registerAttributes();
setHealth(getMaxHealth());
xpReward = Enemy::XP_REWARD_SMALL;
setSize(0.9f, 0.5f);
moveTargetX = 0.0;
moveTargetY = 0.0;
moveTargetZ = 0.0;
moveTargetInitialized = false;
hasAnchor = false;
anchorX = anchorY = anchorZ = 0;
anchorHeight = 10 + random->nextInt(10);
attackPhase = AttackPhase::CIRCLE;
circleAngle = 0.0f;
circleDistance = 5.0f;
circleHeight = 0.0f;
circleClockwise = 1.0f;
flySpeed = 0.1f;
phantomSize = 0;
delete moveControl;
moveControl = new PhantomMoveControl(this);
goalSelector.addGoal(1, new PhantomAttackStrategyGoal(this));
goalSelector.addGoal(2, new PhantomSweepAttackGoal(this));
goalSelector.addGoal(3, new PhantomCircleAroundAnchorGoal(this));
targetSelector.addGoal(1, new PhantomAttackPlayerTargetGoal(this));
}
void Phantom::setPhantomSize(int size)
{
phantomSize = Mth::clamp(size, 0, 64);
float scale = 1.0f + 0.15f * phantomSize;
setSize(0.9f * scale, 0.5f * scale);
getAttribute(SharedMonsterAttributes::ATTACK_DAMAGE)->setBaseValue(6.0 + phantomSize);
}
void Phantom::defineSynchedData()
{
FlyingMob::defineSynchedData();
}
void Phantom::registerAttributes()
{
FlyingMob::registerAttributes();
getAttribute(SharedMonsterAttributes::MAX_HEALTH)->setBaseValue(20.0);
getAttributes()->registerAttribute(SharedMonsterAttributes::ATTACK_DAMAGE)->setBaseValue(6.0);
}
float Phantom::getSoundVolume() { return 1.0f; }
float Phantom::getVoicePitch() { return FlyingMob::getVoicePitch(); }
int Phantom::getAmbientSound() { return eSoundType_MOB_PHANTOM_IDLE; }
int Phantom::getHurtSound() { return eSoundType_MOB_PHANTOM_HURT; }
int Phantom::getDeathSound() { return eSoundType_MOB_PHANTOM_DEATH; }
bool Phantom::isPushable() { return false; }
void Phantom::doPush(shared_ptr<Entity> e) { }
void Phantom::pushEntities() { }
bool Phantom::makeStepSound() { return false; }
void Phantom::causeFallDamage(float distance) { }
void Phantom::checkFallDamage(double ya, bool onGround) { }
bool Phantom::isIgnoringTileTriggers() { return true; }
bool Phantom::onLadder() { return false; }
void Phantom::tick()
{
if (!level->isClientSide && isAlive())
{
if (Calendar::GetMonth() + 1 != 4 || Calendar::GetDayOfMonth() != 1)
{
remove();
return;
hurt(DamageSource::magic, getMaxHealth());
}
}
FlyingMob::tick();
yBodyRot = yRot;
if (!level->isClientSide && isAlive() && tickCount % 20 == 0)
{
playSound(eSoundType_MOB_PHANTOM_FLAP, 1.0f, 1.0f);
}
if (!level->isClientSide && isAlive())
{
if (level->isDay() && !level->isRaining())
{
float br = getBrightness(1.0f);
if (br > 0.5f && level->canSeeSky(
Mth::floor(x), static_cast<int>(floor(y + 0.5)), Mth::floor(z)))
{
setOnFire(8);
}
}
}
}
void Phantom::initAnchor(int bx, int by, int bz)
{
anchorX = bx;
anchorY = by;
anchorZ = bz;
hasAnchor = true;
}
bool Phantom::isTouchingMoveTarget() const
{
double dx = moveTargetX - x;
double dy = moveTargetY - y;
double dz = moveTargetZ - z;
return (dx * dx + dy * dy + dz * dz) < 4.0;
}
bool Phantom::hurt(DamageSource *source, float dmg)
{
if (isInvulnerable()) return false;
return FlyingMob::hurt(source, dmg);
}
bool Phantom::doHurtTarget(shared_ptr<Entity> target)
{
float damage = (float)getAttribute(SharedMonsterAttributes::ATTACK_DAMAGE)->getValue();
return target->hurt(DamageSource::mobAttack(dynamic_pointer_cast<LivingEntity>(shared_from_this())), damage);
}
void Phantom::readAdditionalSaveData(CompoundTag *tag)
{
FlyingMob::readAdditionalSaveData(tag);
setPhantomSize(tag->getInt(L"Size"));
if (tag->contains(L"AnchorX"))
{
anchorX = tag->getInt(L"AnchorX");
anchorY = tag->getInt(L"AnchorY");
anchorZ = tag->getInt(L"AnchorZ");
hasAnchor = true;
}
anchorHeight = 10 + random->nextInt(10);
moveTargetInitialized = false;
}
void Phantom::addAdditonalSaveData(CompoundTag *entityTag)
{
FlyingMob::addAdditonalSaveData(entityTag);
entityTag->putInt(L"Size", phantomSize);
if (hasAnchor)
{
entityTag->putInt(L"AnchorX", anchorX);
entityTag->putInt(L"AnchorY", anchorY);
entityTag->putInt(L"AnchorZ", anchorZ);
}
}
bool Phantom::canSpawn()
{
if (Calendar::GetMonth() + 1 != 4 || Calendar::GetDayOfMonth() != 1) {
return false;
}
int xt = Mth::floor(x);
int yt = static_cast<int>(y);
int zt = Mth::floor(z);
//if (yt < level->seaLevel) return false;
if (level->isDay()) return false;
//if (!level->canSeeSky(xt, yt, zt)) return false;
if (level->getRawBrightness(xt, yt, zt) >= 8) return false;
int topSolidY = level->getTopSolidBlock(xt, zt);
if (topSolidY < level->seaLevel) {
topSolidY = level->seaLevel;
}
if (yt <= topSolidY + 5)
{
int heightBoost = 20 + random->nextInt(15);
yt = topSolidY + heightBoost;
setPos(x, (double)yt, z);
}
if (!level->canSeeSky(xt, yt, zt)) return false;
return FlyingMob::canSpawn();
}

View file

@ -1,85 +0,0 @@
#pragma once
using namespace std;
#include "FlyingMob.h"
#include "Enemy.h"
class Level;
class CompoundTag;
class DamageSource;
class Player;
class Phantom : public FlyingMob, public Enemy
{
friend class PhantomMoveControl;
friend class PhantomAttackStrategyGoal;
friend class PhantomCircleAroundAnchorGoal;
friend class PhantomSweepAttackGoal;
public:
eINSTANCEOF GetType() { return eTYPE_PHANTOM; }
static Entity *create(Level *level) { return new Phantom(level); }
enum class AttackPhase { CIRCLE, SWOOP };
private:
int phantomSize;
double moveTargetX, moveTargetY, moveTargetZ;
bool moveTargetInitialized;
// Orbit anchor
int anchorX, anchorY, anchorZ;
bool hasAnchor;
int anchorHeight;
// Attack
AttackPhase attackPhase;
//Circle
float circleAngle;
float circleDistance;
float circleHeight;
float circleClockwise;
float flySpeed;
public:
Phantom(Level *level);
int getPhantomSize() const { return phantomSize; }
void setPhantomSize(int size);
AttackPhase getAttackPhase() const { return attackPhase; }
virtual bool isPushable();
virtual void tick();
virtual bool hurt(DamageSource *source, float dmg);
virtual void readAdditionalSaveData(CompoundTag *tag);
virtual void addAdditonalSaveData(CompoundTag *entityTag);
virtual bool canSpawn();
virtual bool doHurtTarget(shared_ptr<Entity> target) override;
protected:
virtual void defineSynchedData();
virtual void registerAttributes();
virtual float getSoundVolume();
virtual float getVoicePitch();
virtual int getAmbientSound();
virtual int getHurtSound();
virtual int getDeathSound();
virtual bool useNewAi() override { return true; }
virtual void doPush(shared_ptr<Entity> e);
virtual void pushEntities();
virtual bool makeStepSound();
virtual void causeFallDamage(float distance);
virtual void checkFallDamage(double ya, bool onGround);
virtual bool isIgnoringTileTriggers();
virtual bool onLadder();
private:
void initAnchor(int bx, int by, int bz);
bool isTouchingMoveTarget() const;
};

View file

@ -218,12 +218,7 @@ enum eSOUND_TYPE
eSoundType_MOB_RABBIT_DEATH,
eSoundType_MOB_RABBIT_HOP,
eSoundType_MOB_PHANTOM_BITE,
eSoundType_MOB_PHANTOM_DEATH,
eSoundType_MOB_PHANTOM_FLAP,
eSoundType_MOB_PHANTOM_HURT,
eSoundType_MOB_PHANTOM_IDLE,
eSoundType_MOB_PHANTOM_SWOOP,
eSoundType_MAX
};

View file

@ -1438,6 +1438,8 @@ set(_MINECRAFT_WORLD_COMMON_NET_MINECRAFT_WORLD_LEVEL_LEVELGEN_FEATURE
"${CMAKE_CURRENT_SOURCE_DIR}/BasicTree.h"
"${CMAKE_CURRENT_SOURCE_DIR}/BirchFeature.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/BirchFeature.h"
"${CMAKE_CURRENT_SOURCE_DIR}/BlockBlobFeature.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/BlockBlobFeature.h"
"${CMAKE_CURRENT_SOURCE_DIR}/BonusChestFeature.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/BonusChestFeature.h"
"${CMAKE_CURRENT_SOURCE_DIR}/CactusFeature.cpp"
@ -1468,6 +1470,8 @@ set(_MINECRAFT_WORLD_COMMON_NET_MINECRAFT_WORLD_LEVEL_LEVELGEN_FEATURE
"${CMAKE_CURRENT_SOURCE_DIR}/HouseFeature.h"
"${CMAKE_CURRENT_SOURCE_DIR}/HugeMushroomFeature.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/HugeMushroomFeature.h"
"${CMAKE_CURRENT_SOURCE_DIR}/IceSpikeFeature.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/IceSpikeFeature.h"
"${CMAKE_CURRENT_SOURCE_DIR}/LakeFeature.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/LakeFeature.h"
"${CMAKE_CURRENT_SOURCE_DIR}/LightGemFeature.cpp"
@ -1983,7 +1987,7 @@ set(_MINECRAFT_WORLD_COMMON_NET_MINECRAFT_WORLD_LEVEL_TILE
"${CMAKE_CURRENT_SOURCE_DIR}/BlockPos.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/DoublePlantFeature.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/MutatedBiome.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/Phantom.cpp"
)
source_group("net/minecraft/world/level/tile" FILES ${_MINECRAFT_WORLD_COMMON_NET_MINECRAFT_WORLD_LEVEL_TILE})

View file

@ -28,4 +28,3 @@
//TU 31
#include "Endermite.h"
#include "Phantom.h"