mirror of
https://github.com/celisej567/mcpe.git
synced 2026-09-23 20:09:46 +03:00
* Initial commit.
:)
This commit is contained in:
995
source/World/Entity/Entity.cpp
Normal file
995
source/World/Entity/Entity.cpp
Normal file
@@ -0,0 +1,995 @@
|
||||
#include "Entity.hpp"
|
||||
#include "Player.hpp"
|
||||
#include "Level.hpp"
|
||||
|
||||
int Entity::entityCounter;
|
||||
Random Entity::sharedRandom;
|
||||
|
||||
Entity::Entity(Level* pLevel)
|
||||
{
|
||||
m_pLevel = pLevel;
|
||||
m_EntityID = ++entityCounter;
|
||||
setPos(0, 0, 0);
|
||||
}
|
||||
|
||||
Entity::~Entity()
|
||||
{
|
||||
}
|
||||
|
||||
void Entity::setLevel(Level* pLvl)
|
||||
{
|
||||
m_pLevel = pLvl;
|
||||
}
|
||||
|
||||
void Entity::removed()
|
||||
{
|
||||
m_bRemoved = true;
|
||||
}
|
||||
|
||||
void Entity::setPos(float x, float y, float z)
|
||||
{
|
||||
m_pos = Vec3(x, y, z);
|
||||
|
||||
float halfSize = field_88 / 2;
|
||||
float lowY = y - field_84 + field_A4;
|
||||
|
||||
m_hitbox = AABB(
|
||||
x - halfSize,
|
||||
lowY,
|
||||
z - halfSize,
|
||||
x + halfSize,
|
||||
lowY + field_8C,
|
||||
z + halfSize);
|
||||
}
|
||||
|
||||
void Entity::remove()
|
||||
{
|
||||
m_bRemoved = true;
|
||||
}
|
||||
|
||||
int Entity::move(float x, float y, float z)
|
||||
{
|
||||
float x_1 = x, z_1 = z;
|
||||
|
||||
if (m_bNoCollision)
|
||||
{
|
||||
// just move it. Don't perform any kind of collision
|
||||
m_hitbox.min.x += x;
|
||||
m_hitbox.max.x += x;
|
||||
m_hitbox.min.y += y;
|
||||
m_hitbox.max.y += y;
|
||||
m_hitbox.min.z += z;
|
||||
m_hitbox.max.z += z;
|
||||
|
||||
m_pos.x = (m_hitbox.max.x + m_hitbox.min.x) / 2;
|
||||
m_pos.z = (m_hitbox.max.z + m_hitbox.min.z) / 2;
|
||||
m_pos.y = m_hitbox.min.y + field_84 - field_A4;
|
||||
|
||||
return 1300;
|
||||
}
|
||||
|
||||
//@TODO: untangle the control flow
|
||||
|
||||
float x1, x2, x3, x4, x5, x6;
|
||||
float x7, x8, x9, x10, x11, x12, x20;
|
||||
float x_2, z_2, x_3, z_3;
|
||||
float oldX, oldZ;
|
||||
bool b1, b2, b3, b4, b5, b6;
|
||||
AABB hitold;
|
||||
|
||||
oldX = m_pos.x, oldZ = m_pos.z;
|
||||
|
||||
x7 = m_hitbox.max.z;
|
||||
x8 = m_hitbox.max.y;
|
||||
x9 = m_hitbox.max.x;
|
||||
x10 = m_hitbox.min.z;
|
||||
x11 = m_hitbox.min.y;
|
||||
x12 = m_hitbox.min.x;
|
||||
|
||||
x1 = m_hitbox.max.z;
|
||||
x2 = m_hitbox.max.y;
|
||||
x3 = m_hitbox.max.x;
|
||||
x4 = m_hitbox.min.z;
|
||||
x5 = m_hitbox.min.y;
|
||||
x6 = m_hitbox.min.x;
|
||||
|
||||
if (!field_7C)
|
||||
{
|
||||
label_4:
|
||||
|
||||
z_2 = z_1;
|
||||
b1 = x_1 < 0.0f;
|
||||
b2 = x_1 > 0.0f;
|
||||
x_2 = x_1;
|
||||
b3 = z_1 < 0.0f;
|
||||
b4 = z_1 > 0.0f;
|
||||
b5 = false;
|
||||
goto label_5;
|
||||
}
|
||||
|
||||
if (!isSneaking())
|
||||
goto label_4;
|
||||
|
||||
if (x_1 == 0.0f)
|
||||
{
|
||||
x_2 = x_1;
|
||||
b1 = x_1 < 0.0f;
|
||||
b2 = x_1 > 0.0f;
|
||||
}
|
||||
else
|
||||
{
|
||||
x_2 = x_1;
|
||||
do
|
||||
{
|
||||
AABB aabb = m_hitbox;
|
||||
aabb.move(x_1, -1.0f, 0);
|
||||
|
||||
auto cubes = m_pLevel->getCubes(this, aabb);
|
||||
|
||||
if (cubes->size())
|
||||
break;
|
||||
|
||||
if (x_1 < 0.05f && x_1 >= -0.05f)
|
||||
{
|
||||
x_2 = 0.0f;
|
||||
x_1 = 0.0f;
|
||||
break;
|
||||
}
|
||||
|
||||
// @BUG: See the z_1 part
|
||||
if (x_1 <= 0.0f)
|
||||
x_1 = x_1 + 0.05f;
|
||||
else
|
||||
x_1 = x_1 - 0.05f;
|
||||
|
||||
x_2 = x_1;
|
||||
}
|
||||
while (x_1 != 0.0f);
|
||||
|
||||
b1 = x_1 < 0.0f;
|
||||
b2 = x_1 > 0.0f;
|
||||
}
|
||||
|
||||
if (z_1 == 0.0f)
|
||||
{
|
||||
z_2 = z_1;
|
||||
b3 = z_1 < 0.0f;
|
||||
b4 = z_1 > 0.0f;
|
||||
}
|
||||
else
|
||||
{
|
||||
z_2 = z_1;
|
||||
do
|
||||
{
|
||||
AABB aabb = m_hitbox;
|
||||
aabb.move(0, -1.0f, z_1);
|
||||
|
||||
auto cubes = m_pLevel->getCubes(this, aabb);
|
||||
|
||||
if (cubes->size())
|
||||
break;
|
||||
|
||||
if (z_1 < 0.05f && z_1 >= -0.05f)
|
||||
{
|
||||
z_2 = 0.0f;
|
||||
z_1 = 0.0f;
|
||||
break;
|
||||
}
|
||||
|
||||
//@BUG: wouldn't this loop forever? Since if z_1 == 0.025f, it'd oscillate between -0.025f and +0.025f...
|
||||
if (z_1 <= 0.0f)
|
||||
z_1 = z_1 + 0.05f;
|
||||
else
|
||||
z_1 = z_1 - 0.05f;
|
||||
}
|
||||
while (z_1 != 0.0f);
|
||||
b3 = z_1 < 0.0f;
|
||||
b4 = z_1 > 0.0f;
|
||||
}
|
||||
|
||||
b5 = true;
|
||||
|
||||
label_5:
|
||||
if (b1) x6 += x_1;
|
||||
if (b2) x3 += x_1;
|
||||
if (y < 0.0f) x5 += y;
|
||||
if (y > 0.0f) x2 += y;
|
||||
if (b3) x4 += z;
|
||||
if (b4) x1 += z;
|
||||
|
||||
AABB scanAABB(x6, x5, x4, x3, x2, x1);
|
||||
auto pCubes = m_pLevel->getCubes(this, scanAABB);
|
||||
|
||||
float newY = y;
|
||||
for (const auto &aabb : (*pCubes))
|
||||
newY = aabb.clipYCollide(m_hitbox, newY);
|
||||
|
||||
m_hitbox.move(0, newY, 0);
|
||||
|
||||
if (!field_81 && newY != y)
|
||||
{
|
||||
z_1 = 0.0f;
|
||||
x_1 = 0.0f;
|
||||
newY = 0.0f;
|
||||
}
|
||||
|
||||
if (field_7C)
|
||||
{
|
||||
b6 = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
b6 = y < 0.0f;
|
||||
if (newY == y)
|
||||
b6 = 0;
|
||||
}
|
||||
|
||||
for (const auto& aabb : (*pCubes))
|
||||
x_1 = aabb.clipXCollide(m_hitbox, x_1);
|
||||
|
||||
m_hitbox.move(x_1, 0, 0);
|
||||
|
||||
if (!field_81 && x_1 != x_2)
|
||||
{
|
||||
z_1 = 0.0f;
|
||||
x_1 = 0.0f;
|
||||
newY = 0.0f;
|
||||
}
|
||||
|
||||
for (const auto& aabb : (*pCubes))
|
||||
z_1 = aabb.clipZCollide(m_hitbox, z_1);
|
||||
|
||||
m_hitbox.move(0, 0, z_1);
|
||||
|
||||
if (!field_81 && z_1 != z_2)
|
||||
{
|
||||
z_1 = 0.0f;
|
||||
x_1 = 0.0f;
|
||||
newY = 0.0f;
|
||||
}
|
||||
|
||||
x20 = field_A8;
|
||||
if (x20 <= 0.0f || !b6)
|
||||
{
|
||||
label_44:
|
||||
z_3 = z_1;
|
||||
x_3 = x_1;
|
||||
goto label_45;
|
||||
}
|
||||
|
||||
if (field_A4 >= 0.05f || x_2 == x_1 && z_2 == z_1)
|
||||
goto label_44;
|
||||
|
||||
// oh come on, undoing all our work??
|
||||
hitold = m_hitbox;
|
||||
m_hitbox = AABB(x12, x11, x10, x9, x8, x7);
|
||||
|
||||
if (b1) x12 += x_2;
|
||||
if (b2) x9 += x_2;
|
||||
x8 += x20; //@BUG: missing if (x20 > 0) check?
|
||||
if (x20 < 0.0f) x11 += x20;
|
||||
if (b3) x10 += z_2;
|
||||
if (b4) x7 += z_2;
|
||||
|
||||
{
|
||||
AABB scanAABB2(x12, x11, x10, x9, x8, x7);
|
||||
|
||||
//@BUG: useless copy
|
||||
//@BUG: this doesn't actually copy anything
|
||||
*pCubes = *m_pLevel->getCubes(this, scanAABB2);
|
||||
}
|
||||
|
||||
for (const auto& aabb : (*pCubes))
|
||||
x20 = aabb.clipYCollide(m_hitbox, x20);
|
||||
|
||||
m_hitbox.move(0, x20, 0);
|
||||
|
||||
if (field_81 || x20 == y)
|
||||
{
|
||||
z_3 = z_2;
|
||||
x_3 = x_2;
|
||||
}
|
||||
else
|
||||
{
|
||||
x20 = 0.0f;
|
||||
z_3 = 0.0f;
|
||||
x_3 = 0.0f;
|
||||
}
|
||||
|
||||
for (const auto& aabb : (*pCubes))
|
||||
x_3 = aabb.clipXCollide(m_hitbox, x_3);
|
||||
|
||||
m_hitbox.move(x_3, 0, 0);
|
||||
|
||||
if (!field_81 && x_2 != x_3)
|
||||
{
|
||||
x20 = 0.0f;
|
||||
z_3 = 0.0f;
|
||||
x_3 = 0.0f;
|
||||
}
|
||||
|
||||
for (const auto& aabb : (*pCubes))
|
||||
z_3 = aabb.clipZCollide(m_hitbox, z_3);
|
||||
|
||||
m_hitbox.move(0, 0, z_3);
|
||||
|
||||
if (!field_81 && z_2 != z_3)
|
||||
{
|
||||
x20 = 0.0f;
|
||||
z_3 = 0.0f;
|
||||
x_3 = 0.0f;
|
||||
}
|
||||
|
||||
// if we moved more this time than before?? no clue wtf this is about...
|
||||
if (z_1 * z_1 + x_1 * x_1 < z_3 * z_3 + x_3 * x_3)
|
||||
{
|
||||
field_A4 += 0.5f;
|
||||
newY = x20;
|
||||
}
|
||||
else
|
||||
{
|
||||
// don't get the rationale behind this at all...
|
||||
m_hitbox = hitold;
|
||||
z_3 = z_1;
|
||||
x_3 = x_1;
|
||||
}
|
||||
|
||||
label_45:
|
||||
m_pos.x = (m_hitbox.min.x + m_hitbox.max.x) / 2;
|
||||
m_pos.z = (m_hitbox.min.z + m_hitbox.max.z) / 2;
|
||||
m_pos.y = m_hitbox.min.y - field_A4 + field_84;
|
||||
|
||||
field_7D = x_2 != x_3 || z_2 != z_3;
|
||||
field_7F = field_7D || newY != y;
|
||||
field_7C = y < 0.0f && newY != y;
|
||||
field_7E = newY != y;
|
||||
|
||||
checkFallDamage(newY, field_7C);
|
||||
|
||||
if (x_2 != x_3) m_vel.x = 0.0;
|
||||
if (newY != y) m_vel.y = 0.0;
|
||||
if (z_2 != z_3) m_vel.z = 0.0;
|
||||
|
||||
if (!b5)
|
||||
{
|
||||
float diffX = (m_pos.x - oldX), diffZ = (m_pos.z - oldZ);
|
||||
field_94 += Mth::sqrt(diffZ * diffZ + diffX * diffX) * 0.6f;
|
||||
|
||||
int tileX = Mth::floor(m_pos.x);
|
||||
int tileY = Mth::floor(m_pos.y - 0.2f - field_84);
|
||||
int tileZ = Mth::floor(m_pos.z);
|
||||
|
||||
TileID tileID = m_pLevel->getTile(tileX, tileY, tileZ);
|
||||
|
||||
if (tileID > 0 && field_94 > float(field_D8))
|
||||
{
|
||||
++field_D8;
|
||||
bool bPlaySound = true;
|
||||
|
||||
auto sound = Tile::tiles[tileID]->m_pSound;
|
||||
if (m_pLevel->getTile(tileX, tileY + 1, tileZ) == Tile::topSnow->m_ID)
|
||||
sound = Tile::topSnow->m_pSound;
|
||||
else if (Tile::tiles[tileID]->m_pMaterial->isLiquid())
|
||||
bPlaySound = false;
|
||||
|
||||
if (bPlaySound)
|
||||
m_pLevel->playSound(this, "step." + sound->m_name, sound->field_18 * 0.15f, sound->field_1C);
|
||||
|
||||
Tile::tiles[tileID]->stepOn(m_pLevel, tileX, tileY, tileZ, this);
|
||||
}
|
||||
}
|
||||
|
||||
// Check whether the entity is inside of any tiles.
|
||||
|
||||
int minX = Mth::floor(m_hitbox.min.x), minY = Mth::floor(m_hitbox.min.y), minZ = Mth::floor(m_hitbox.min.z),
|
||||
maxX = Mth::floor(m_hitbox.max.x), maxY = Mth::floor(m_hitbox.max.y), maxZ = Mth::floor(m_hitbox.max.z);
|
||||
|
||||
if (m_pLevel->hasChunksAt(minX, minY, minZ, maxX, maxY, maxZ))
|
||||
{
|
||||
for (int x = minX; x <= maxX; x++)
|
||||
for (int y = minY; y <= maxY; y++)
|
||||
for (int z = minZ; z <= maxZ; z++)
|
||||
{
|
||||
TileID tileID = m_pLevel->getTile(x, y, z);
|
||||
if (tileID > 0)
|
||||
Tile::tiles[tileID]->entityInside(m_pLevel, x, y, z, this);
|
||||
}
|
||||
}
|
||||
|
||||
field_A4 *= 0.4f;
|
||||
|
||||
bool bIsInWater = isInWater();
|
||||
|
||||
if (m_pLevel->containsFireTile(m_hitbox))
|
||||
{
|
||||
burn(true);
|
||||
|
||||
if (bIsInWater)
|
||||
{
|
||||
label_76:
|
||||
if (field_C0 > 0)
|
||||
field_C0 = -field_C4;
|
||||
|
||||
return 1300;
|
||||
}
|
||||
|
||||
field_C0++;
|
||||
if (field_C0 == 0)
|
||||
field_C0 = 300;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (field_C0 <= 0)
|
||||
field_C0 = -field_C4;
|
||||
|
||||
if (bIsInWater)
|
||||
goto label_76;
|
||||
}
|
||||
|
||||
return 1300;
|
||||
}
|
||||
|
||||
void Entity::moveTo(float x, float y, float z, float yaw, float pitch)
|
||||
{
|
||||
y += field_84;
|
||||
|
||||
m_pos.x = x;
|
||||
m_yaw = yaw;
|
||||
field_3C.x = x;
|
||||
field_98.x = x;
|
||||
|
||||
m_pos.z = z;
|
||||
m_pitch = pitch;
|
||||
field_3C.z = z;
|
||||
field_98.z = z;
|
||||
|
||||
m_pos.y = y;
|
||||
field_3C.y = y;
|
||||
field_98.y = y;
|
||||
|
||||
setPos(x, y, z);
|
||||
}
|
||||
|
||||
void Entity::absMoveTo(float x, float y, float z, float yaw, float pitch)
|
||||
{
|
||||
field_A4 = 0.0f;
|
||||
|
||||
field_5C = yaw;
|
||||
m_yaw = yaw;
|
||||
m_pitch = pitch;
|
||||
field_60 = pitch;
|
||||
|
||||
m_pos.x = x;
|
||||
field_3C.x = x;
|
||||
m_pos.y = y;
|
||||
field_3C.y = y;
|
||||
m_pos.z = z;
|
||||
field_3C.z = z;
|
||||
|
||||
//@WHAT: (yaw - yaw) == 0
|
||||
if (yaw - yaw < -180.0f)
|
||||
field_5C = yaw + 360.0f;
|
||||
if (yaw - yaw >= 180.0f)
|
||||
field_5C = field_5C - 360.0f;
|
||||
|
||||
setPos(this->m_pos.x, this->m_pos.y, this->m_pos.z);
|
||||
return setRot(yaw, pitch);
|
||||
}
|
||||
|
||||
void Entity::moveRelative(float x, float z, float y)
|
||||
{
|
||||
float d = sqrtf(x * x + z * z);
|
||||
if (d < 0.01f) return;
|
||||
if (d > 1.0f)
|
||||
d = 1.0f;
|
||||
|
||||
y /= d;
|
||||
x *= y;
|
||||
z *= y;
|
||||
|
||||
float yaw = m_yaw * float(M_PI);
|
||||
float syaw = sinf(yaw / 180.0f);
|
||||
float cyaw = cosf(yaw / 180.0f);
|
||||
|
||||
m_vel.x += x * cyaw - z * syaw;
|
||||
m_vel.z += x * syaw + z * cyaw;
|
||||
}
|
||||
|
||||
void Entity::lerpTo(float x, float y, float z, float yaw, float pitch, int p)
|
||||
{
|
||||
setPos(x, y, z);
|
||||
setRot(yaw, pitch);
|
||||
}
|
||||
|
||||
void Entity::lerpMotion(float x, float y, float z)
|
||||
{
|
||||
m_vel = Vec3(x, y, z);
|
||||
}
|
||||
|
||||
void Entity::turn(float yaw, float pitch)
|
||||
{
|
||||
float y_old = m_yaw;
|
||||
float p_old = m_pitch;
|
||||
|
||||
m_yaw += yaw * 0.15f;
|
||||
m_pitch -= pitch * 0.15f;
|
||||
|
||||
// can't rotate more than facing fully up or fully down
|
||||
if (m_pitch < -90.0f)
|
||||
m_pitch = -90.0f;
|
||||
if (m_pitch > 90.0f)
|
||||
m_pitch = 90.0f;
|
||||
|
||||
field_5C += m_yaw - y_old;
|
||||
field_60 += m_pitch - p_old;
|
||||
}
|
||||
|
||||
void Entity::interpolateTurn(float yaw, float pitch)
|
||||
{
|
||||
m_yaw += yaw * 0.15f;
|
||||
m_pitch -= pitch * 0.15f;
|
||||
|
||||
// can't rotate more than facing fully up or fully down
|
||||
if (m_pitch < -90.0f)
|
||||
m_pitch = -90.0f;
|
||||
if (m_pitch > 90.0f)
|
||||
m_pitch = 90.0f;
|
||||
}
|
||||
|
||||
void Entity::tick()
|
||||
{
|
||||
baseTick();
|
||||
}
|
||||
|
||||
void Entity::baseTick()
|
||||
{
|
||||
//@TODO: untangle the gotos
|
||||
|
||||
field_90 = field_94;
|
||||
field_3C = m_pos;
|
||||
field_B4++;
|
||||
field_5C = m_yaw;
|
||||
field_60 = m_pitch;
|
||||
if (isInWater())
|
||||
{
|
||||
if (!field_D4 && !field_D6)
|
||||
{
|
||||
float dist = sqrtf(m_vel.y * m_vel.y + m_vel.x * m_vel.x * 0.2f + m_vel.z * m_vel.z * 0.2f) * 0.2f;
|
||||
if (dist > 1.0f)
|
||||
dist = 1.0f;
|
||||
|
||||
m_pLevel->playSound(this, "random.splash", dist, 1.0f + 0.4f * (sharedRandom.nextFloat() - sharedRandom.nextFloat()));
|
||||
|
||||
float f1 = floorf(m_hitbox.min.y);
|
||||
|
||||
for (int i = 0; float(i) < field_88 * 20.0f + 1.0f; i++)
|
||||
{
|
||||
m_pLevel->addParticle(
|
||||
"bubble",
|
||||
m_pos.x + field_88 * (sharedRandom.nextFloat() * 2.0f - 1.0f),
|
||||
f1 + 1.0f,
|
||||
m_pos.z + field_88 * (sharedRandom.nextFloat() * 2.0f - 1.0f),
|
||||
m_vel.x,
|
||||
m_vel.y - 0.2f * sharedRandom.nextFloat(),
|
||||
m_vel.z
|
||||
);
|
||||
}
|
||||
|
||||
for (int i = 0; float(i) < field_88 * 20.0f + 1.0f; i++)
|
||||
{
|
||||
m_pLevel->addParticle(
|
||||
"splash",
|
||||
m_pos.x + field_88 * (sharedRandom.nextFloat() * 2.0f - 1.0f),
|
||||
f1 + 1.0f,
|
||||
m_pos.z + field_88 * (sharedRandom.nextFloat() * 2.0f - 1.0f),
|
||||
m_vel.x,
|
||||
m_vel.y - 0.2f * sharedRandom.nextFloat(),
|
||||
m_vel.z
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
field_D4 = true;
|
||||
field_C0 = 0;
|
||||
m_distanceFallen = 0;
|
||||
|
||||
if (m_pLevel->field_11)
|
||||
goto label_4;
|
||||
}
|
||||
else
|
||||
{
|
||||
field_D4 = false;
|
||||
|
||||
if (m_pLevel->field_11)
|
||||
{
|
||||
label_4:
|
||||
field_C0 = 0;
|
||||
goto label_5;
|
||||
}
|
||||
}
|
||||
|
||||
if (field_C0 <= 0)
|
||||
{
|
||||
label_5:
|
||||
if (!isInLava())
|
||||
goto label_6;
|
||||
goto label_15;
|
||||
}
|
||||
|
||||
if (field_D5)
|
||||
{
|
||||
field_C0 -= 4;
|
||||
if (field_C0 < 0)
|
||||
field_C0 = 0;
|
||||
goto label_5;
|
||||
}
|
||||
|
||||
if (field_C0 % 20 == 0)
|
||||
{
|
||||
hurt(nullptr, true);
|
||||
}
|
||||
|
||||
field_C0--;
|
||||
|
||||
if (isInLava())
|
||||
{
|
||||
label_15:
|
||||
lavaHurt();
|
||||
}
|
||||
|
||||
label_6:
|
||||
if (m_pos.y < -64.0f)
|
||||
outOfWorld();
|
||||
|
||||
field_D6 = false;
|
||||
}
|
||||
|
||||
bool Entity::intersects(float minX, float minY, float minZ, float maxX, float maxY, float maxZ)
|
||||
{
|
||||
AABB aabb(minX, minY, minZ, maxX, maxY, maxZ);
|
||||
return aabb.intersect(m_hitbox);
|
||||
}
|
||||
|
||||
bool Entity::isFree(float offX, float offY, float offZ)
|
||||
{
|
||||
AABB aabb = m_hitbox;
|
||||
aabb.move(offX, offY, offZ);
|
||||
|
||||
auto pCubes = m_pLevel->getCubes(this, aabb);
|
||||
if (!pCubes)
|
||||
return false;
|
||||
|
||||
return !m_pLevel->containsAnyLiquid(aabb);
|
||||
}
|
||||
|
||||
bool Entity::isFree(float offX, float offY, float offZ, float expand)
|
||||
{
|
||||
AABB aabb = m_hitbox;
|
||||
aabb.move(offX, offY, offZ);
|
||||
aabb.grow(expand, expand, expand);
|
||||
|
||||
auto pCubes = m_pLevel->getCubes(this, aabb);
|
||||
if (!pCubes)
|
||||
return false;
|
||||
|
||||
return !m_pLevel->containsAnyLiquid(aabb);
|
||||
}
|
||||
|
||||
bool Entity::isInWall()
|
||||
{
|
||||
return m_pLevel->isSolidTile(Mth::floor(m_pos.x), Mth::floor(m_pos.y + getHeadHeight()), Mth::floor(m_pos.z));
|
||||
}
|
||||
|
||||
bool Entity::isInWater()
|
||||
{
|
||||
AABB aabb = m_hitbox;
|
||||
aabb.grow(0, -0.4f, 0);
|
||||
return m_pLevel->checkAndHandleWater(aabb, Material::water, this);
|
||||
}
|
||||
|
||||
bool Entity::isInLava()
|
||||
{
|
||||
AABB aabb = m_hitbox;
|
||||
aabb.grow(-0.1f, -0.4f, -0.1f);
|
||||
return m_pLevel->containsMaterial(aabb, Material::lava);
|
||||
}
|
||||
|
||||
bool Entity::isUnderLiquid(Material* pMtl)
|
||||
{
|
||||
int tileX = Mth::floor(m_pos.x);
|
||||
int tileY = Mth::floor(m_pos.y + getHeadHeight());
|
||||
int tileZ = Mth::floor(m_pos.z);
|
||||
|
||||
Tile* pTile = Tile::tiles[m_pLevel->getTile(tileX, tileY, tileZ)];
|
||||
if (!pTile || pTile->m_pMaterial != pMtl)
|
||||
return false;
|
||||
|
||||
int data = m_pLevel->getData(tileX, tileY, tileZ);
|
||||
int level = data <= 7 ? data + 1 : 1;
|
||||
|
||||
return float(tileY) < float(tileY + 1) - (float(level) / 9.0f - 0.11111f);
|
||||
}
|
||||
|
||||
float Entity::getHeadHeight()
|
||||
{
|
||||
return 0.0f;
|
||||
}
|
||||
|
||||
float Entity::getShadowHeightOffs()
|
||||
{
|
||||
return field_8C / 2.0f;
|
||||
}
|
||||
|
||||
float Entity::getBrightness(float f)
|
||||
{
|
||||
int tileX = Mth::floor(m_pos.x);
|
||||
int tileY = Mth::floor(m_pos.y - field_84 + (m_hitbox.max.y - m_hitbox.min.y) * 0.66f);
|
||||
int tileZ = Mth::floor(m_pos.z);
|
||||
|
||||
int minX = Mth::floor(m_hitbox.min.x);
|
||||
int minY = Mth::floor(m_hitbox.min.y);
|
||||
int minZ = Mth::floor(m_hitbox.min.z);
|
||||
int maxX = Mth::floor(m_hitbox.max.x);
|
||||
int maxY = Mth::floor(m_hitbox.max.y);
|
||||
int maxZ = Mth::floor(m_hitbox.max.z);
|
||||
|
||||
if (!m_pLevel->hasChunksAt(minX, minY, minZ, maxX, maxY, maxZ))
|
||||
return 0;
|
||||
|
||||
return m_pLevel->getBrightness(tileX, tileY, tileZ);
|
||||
}
|
||||
|
||||
float Entity::distanceTo(Entity* pEnt)
|
||||
{
|
||||
return distanceTo(pEnt->m_pos.x, pEnt->m_pos.y, pEnt->m_pos.z);
|
||||
}
|
||||
|
||||
float Entity::distanceTo(float x, float y, float z)
|
||||
{
|
||||
return sqrtf(distanceToSqr(x, y, z));
|
||||
}
|
||||
|
||||
float Entity::distanceToSqr(Entity* pEnt)
|
||||
{
|
||||
return distanceToSqr(pEnt->m_pos.x, pEnt->m_pos.y, pEnt->m_pos.z);
|
||||
}
|
||||
|
||||
float Entity::distanceToSqr(float x, float y, float z)
|
||||
{
|
||||
float diffX = m_pos.x - x;
|
||||
float diffY = m_pos.y - y;
|
||||
float diffZ = m_pos.z - z;
|
||||
|
||||
return diffX * diffX + diffY * diffY + diffZ * diffZ;
|
||||
}
|
||||
|
||||
int Entity::interactPreventDefault()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool Entity::interact(Player* player)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
void Entity::playerTouch(Player* player)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void Entity::push(Entity* bud)
|
||||
{
|
||||
float diffX = bud->m_pos.x - m_pos.x;
|
||||
float diffZ = bud->m_pos.z - m_pos.z;
|
||||
float maxDiff = Mth::absMax(diffX, diffZ);
|
||||
|
||||
if (maxDiff < 0.01f) return;
|
||||
|
||||
float x1 = sqrtf(maxDiff);
|
||||
float x2 = 1.0f / x1;
|
||||
if (x2 > 1.0f)
|
||||
x2 = 1.0f;
|
||||
float x3 = 1.0f - this->field_B0;
|
||||
float x4 = x3 * diffX / x1 * x2 * 0.05f;
|
||||
|
||||
push(-x4, 0.0f, -x4);
|
||||
bud->push(x4, 0.0f, x4);
|
||||
}
|
||||
|
||||
void Entity::push(float x, float y, float z)
|
||||
{
|
||||
m_vel.x += x;
|
||||
m_vel.y += y;
|
||||
m_vel.z += z;
|
||||
}
|
||||
|
||||
bool Entity::isPickable()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Entity::isPushable()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Entity::isShootable()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Entity::isSneaking()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Entity::isAlive()
|
||||
{
|
||||
return m_bRemoved;
|
||||
}
|
||||
|
||||
bool Entity::isOnFire()
|
||||
{
|
||||
return field_C0 > 0;
|
||||
}
|
||||
|
||||
bool Entity::isPlayer()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Entity::isCreativeModeAllowed()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Entity::shouldRender(Vec3& camPos)
|
||||
{
|
||||
return shouldRenderAtSqrDistance(distanceToSqr(camPos.x, camPos.y, camPos.z));
|
||||
}
|
||||
|
||||
bool Entity::shouldRenderAtSqrDistance(float distSqr)
|
||||
{
|
||||
float maxDist = (field_30 * 64.0f) * (((m_hitbox.max.z - m_hitbox.min.z) + (m_hitbox.max.x - m_hitbox.min.x) + (m_hitbox.max.y - m_hitbox.min.y)) / 3.0f);
|
||||
|
||||
return maxDist * maxDist > distSqr;
|
||||
}
|
||||
|
||||
bool Entity::hurt(Entity* pAttacker, int damage)
|
||||
{
|
||||
markHurt();
|
||||
return 0;
|
||||
}
|
||||
|
||||
void Entity::animateHurt()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
float Entity::getPickRadius()
|
||||
{
|
||||
return 0.1f;
|
||||
}
|
||||
|
||||
|
||||
void Entity::awardKillScore(Entity* pKilled, int score)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void Entity::setEquippedSlot(int a, int b, int c)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void Entity::setRot(float yaw, float pitch)
|
||||
{
|
||||
m_yaw = yaw;
|
||||
m_pitch = pitch;
|
||||
}
|
||||
|
||||
void Entity::setSize(float rad, float height)
|
||||
{
|
||||
field_88 = rad;
|
||||
field_8C = height;
|
||||
}
|
||||
|
||||
void Entity::setPos(EntityPos* pPos)
|
||||
{
|
||||
if (pPos->m_bHasPos)
|
||||
setPos(pPos->m_pos.x, pPos->m_pos.y, pPos->m_pos.z);
|
||||
else
|
||||
setPos(m_pos.x, m_pos.y, m_pos.z);
|
||||
|
||||
if (pPos->m_bHasRot)
|
||||
setRot(pPos->m_yaw, pPos->m_pitch);
|
||||
else
|
||||
setRot(m_yaw, m_pitch);
|
||||
}
|
||||
|
||||
void Entity::resetPos()
|
||||
{
|
||||
if (!m_pLevel)
|
||||
// No level? Fine
|
||||
return;
|
||||
|
||||
if (m_pos.y <= 0.0f)
|
||||
// It's in the void. It's probably not inside of any tiles.
|
||||
return;
|
||||
|
||||
// Push the entity up while it's inside solid tiles.
|
||||
while (true)
|
||||
{
|
||||
setPos(m_pos.x, m_pos.y, m_pos.z);
|
||||
|
||||
auto pCubes = m_pLevel->getCubes(this, m_hitbox);
|
||||
|
||||
// if we aren't inside any tiles, great!
|
||||
if (!pCubes->size())
|
||||
break;
|
||||
|
||||
m_pos.y += 1.0f;
|
||||
}
|
||||
|
||||
m_vel.x = 0.0f;
|
||||
m_vel.y = 0.0f;
|
||||
m_vel.z = 0.0f;
|
||||
m_pitch = 0.0f;
|
||||
}
|
||||
|
||||
void Entity::outOfWorld()
|
||||
{
|
||||
remove();
|
||||
}
|
||||
|
||||
void Entity::checkFallDamage(float fDeltaY, bool bHitGround)
|
||||
{
|
||||
if (bHitGround)
|
||||
{
|
||||
if (m_distanceFallen > 0.0f)
|
||||
{
|
||||
causeFallDamage(m_distanceFallen);
|
||||
m_distanceFallen = 0.0f;
|
||||
}
|
||||
}
|
||||
else if (fDeltaY < 0.0f)
|
||||
{
|
||||
m_distanceFallen -= fDeltaY;
|
||||
}
|
||||
}
|
||||
|
||||
void Entity::causeFallDamage(float f)
|
||||
{
|
||||
// stub
|
||||
}
|
||||
|
||||
void Entity::markHurt()
|
||||
{
|
||||
m_bHurt = true;
|
||||
}
|
||||
|
||||
void Entity::burn(int x)
|
||||
{
|
||||
if (!field_D5)
|
||||
hurt(nullptr, 4);
|
||||
}
|
||||
|
||||
void Entity::lavaHurt()
|
||||
{
|
||||
if (!field_D5)
|
||||
{
|
||||
hurt(nullptr, 4);
|
||||
field_C0 = 600;
|
||||
}
|
||||
}
|
||||
|
||||
int Entity::hashCode()
|
||||
{
|
||||
return m_EntityID;
|
||||
}
|
||||
|
||||
bool Entity::operator==(const Entity& other) const
|
||||
{
|
||||
return m_EntityID == other.m_EntityID;
|
||||
}
|
||||
191
source/World/Entity/Entity.hpp
Normal file
191
source/World/Entity/Entity.hpp
Normal file
@@ -0,0 +1,191 @@
|
||||
#pragma once
|
||||
|
||||
#include "AABB.hpp"
|
||||
#include "Vec3.hpp"
|
||||
#include "Material.hpp"
|
||||
#include "Tile.hpp"
|
||||
#include "ItemInstance.hpp"
|
||||
|
||||
class Level;
|
||||
class Player;
|
||||
class ItemInstance;
|
||||
|
||||
enum eEntityRenderType
|
||||
{
|
||||
RENDER_NONE,
|
||||
RENDER_TNT,
|
||||
RENDER_HUMANOID,
|
||||
RENDER_ITEM,
|
||||
RENDER_CAMERA,
|
||||
|
||||
// custom
|
||||
RENDER_FALLING_TILE = 50,
|
||||
};
|
||||
|
||||
struct EntityPos
|
||||
{
|
||||
Vec3 m_pos;
|
||||
float m_yaw = 0, m_pitch = 0;
|
||||
bool m_bHasRot = false, m_bHasPos = false;
|
||||
|
||||
EntityPos() {};
|
||||
|
||||
EntityPos(const Vec3& pos)
|
||||
{
|
||||
m_pos = pos;
|
||||
m_bHasPos = true;
|
||||
}
|
||||
|
||||
EntityPos(float yaw, float pitch)
|
||||
{
|
||||
m_yaw = yaw;
|
||||
m_pitch = pitch;
|
||||
m_bHasRot = true;
|
||||
}
|
||||
|
||||
EntityPos(const Vec3& pos, float yaw, float pitch)
|
||||
{
|
||||
m_pos = pos;
|
||||
m_yaw = yaw;
|
||||
m_pitch = pitch;
|
||||
m_bHasPos = true;
|
||||
m_bHasRot = true;
|
||||
}
|
||||
};
|
||||
|
||||
class Entity
|
||||
{
|
||||
public:
|
||||
Entity(Level*);
|
||||
virtual ~Entity();
|
||||
virtual void setLevel(Level*);
|
||||
virtual void removed();
|
||||
virtual void setPos(float x, float y, float z);
|
||||
virtual void remove();
|
||||
virtual int move(float x, float y, float z);
|
||||
virtual void moveTo(float x, float y, float z, float yaw, float pitch);
|
||||
virtual void absMoveTo(float x, float y, float z, float yaw, float pitch);
|
||||
virtual void moveRelative(float x, float z, float y);
|
||||
virtual void lerpTo(float x, float y, float z, float yaw, float pitch, int i);
|
||||
virtual void lerpMotion(float x, float y, float z);
|
||||
virtual void turn(float yaw, float pitch);
|
||||
virtual void interpolateTurn(float yaw, float pitch);
|
||||
virtual void tick();
|
||||
virtual void baseTick();
|
||||
virtual bool intersects(float minX, float minY, float minZ, float maxX, float maxY, float maxZ);
|
||||
virtual bool isFree(float offX, float offY, float offZ);
|
||||
virtual bool isFree(float offX, float offY, float offZ, float expand);
|
||||
virtual bool isInWall();
|
||||
virtual bool isInWater();
|
||||
virtual bool isInLava();
|
||||
virtual bool isUnderLiquid(Material*);
|
||||
virtual float getHeadHeight();
|
||||
virtual float getShadowHeightOffs();
|
||||
virtual float getBrightness(float f);
|
||||
virtual float distanceTo(Entity*);
|
||||
virtual float distanceToSqr(float x, float y, float z);
|
||||
virtual float distanceTo(float x, float y, float z);
|
||||
virtual float distanceToSqr(Entity*);
|
||||
virtual int interactPreventDefault();
|
||||
virtual bool interact(Player*);
|
||||
virtual void playerTouch(Player*);
|
||||
virtual void push(Entity*);
|
||||
virtual void push(float x, float y, float z);
|
||||
virtual bool isPickable();
|
||||
virtual bool isPushable();
|
||||
virtual bool isShootable();
|
||||
virtual bool isSneaking();
|
||||
virtual bool isAlive();
|
||||
virtual bool isOnFire();
|
||||
virtual bool isPlayer();
|
||||
virtual bool isCreativeModeAllowed();
|
||||
virtual bool shouldRender(Vec3& camPos);
|
||||
virtual bool shouldRenderAtSqrDistance(float distSqr);
|
||||
virtual bool hurt(Entity*, int);
|
||||
virtual void animateHurt();
|
||||
virtual float getPickRadius();
|
||||
// virtual void spawnAtLocation(ItemInstance*, float);
|
||||
// virtual void spawnAtLocation(int, int);
|
||||
// virtual void spawnAtLocation(int, int, float);
|
||||
virtual void awardKillScore(Entity* pKilled, int score);
|
||||
virtual void setEquippedSlot(int, int, int);
|
||||
virtual void setRot(float yaw, float pitch);
|
||||
virtual void setSize(float rad, float height);
|
||||
virtual void setPos(EntityPos*);
|
||||
virtual void resetPos();
|
||||
virtual void outOfWorld();
|
||||
virtual void checkFallDamage(float f, bool b);
|
||||
virtual void causeFallDamage(float f);
|
||||
virtual void markHurt();
|
||||
virtual void burn(int);
|
||||
virtual void lavaHurt();
|
||||
|
||||
int hashCode();
|
||||
|
||||
bool operator==(const Entity& other) const;
|
||||
|
||||
float distanceToSqr_inline(float x, float y, float z) const
|
||||
{
|
||||
return
|
||||
(m_pos.x - x) * (m_pos.x - x) +
|
||||
(m_pos.y - y) * (m_pos.y - y) +
|
||||
(m_pos.z - z) * (m_pos.z - z);
|
||||
}
|
||||
|
||||
public:
|
||||
static int entityCounter;
|
||||
static Random sharedRandom;
|
||||
|
||||
Vec3 m_pos;
|
||||
bool m_bInAChunk = false;
|
||||
int m_chunkX = 0;
|
||||
int m_chunkY = 0;
|
||||
int m_chunkZ = 0;
|
||||
int field_20 = 0;
|
||||
int field_24 = 0;
|
||||
int field_28 = 0;
|
||||
int m_EntityID;
|
||||
float field_30 = 1.0f;
|
||||
uint8_t field_34 = 0;
|
||||
Level* m_pLevel = nullptr;
|
||||
Vec3 field_3C;
|
||||
Vec3 m_vel;
|
||||
float m_yaw = 0.0f;
|
||||
float m_pitch = 0.0f;
|
||||
//maybe these are the actual m_yaw and m_pitch, and
|
||||
//the one I annotated are the destination yaw and pitch.
|
||||
//interpolateTurn doesn't modify them, so I highly suspect
|
||||
//this to be the case.
|
||||
float field_5C = 0.0f;
|
||||
float field_60 = 0.0f;
|
||||
AABB m_hitbox;
|
||||
bool field_7C = false;
|
||||
bool field_7D = false;
|
||||
bool field_7E = false;
|
||||
bool field_7F = false;
|
||||
bool m_bHurt = false;
|
||||
uint8_t field_81 = 1;
|
||||
bool m_bRemoved = false;
|
||||
float field_84 = 0.0f;
|
||||
float field_88 = 0.6f;
|
||||
float field_8C = 1.8f;
|
||||
float field_90 = 0.0f;
|
||||
float field_94 = 0.0f;
|
||||
Vec3 field_98;
|
||||
float field_A4 = 0.0f;
|
||||
float field_A8 = 0.0f;
|
||||
bool m_bNoCollision = false;
|
||||
float field_B0 = 0.0f;
|
||||
int field_B4 = 0;
|
||||
int field_B8 = 0;
|
||||
int field_BC = 300;
|
||||
int field_C0 = 0;
|
||||
int field_C4;
|
||||
int field_C8 = 0; // @NOTE: Render type? (eEntityRenderType)
|
||||
float m_distanceFallen = 0.0f;
|
||||
int field_D0 = 300;
|
||||
uint8_t field_D4 = 0;
|
||||
bool field_D5 = false;
|
||||
bool field_D6 = true;
|
||||
int field_D8 = 1;
|
||||
};
|
||||
84
source/World/Entity/FallingTile.cpp
Normal file
84
source/World/Entity/FallingTile.cpp
Normal file
@@ -0,0 +1,84 @@
|
||||
#include "FallingTile.hpp"
|
||||
#include "Level.hpp"
|
||||
|
||||
FallingTile::FallingTile(Level* level) : Entity(level)
|
||||
{
|
||||
}
|
||||
|
||||
FallingTile::FallingTile(Level* level, float x, float y, float z, int id) : Entity(level)
|
||||
{
|
||||
m_id = id;
|
||||
field_34 = 1;
|
||||
setSize(0.98f, 0.98f);
|
||||
field_84 = field_8C * 0.5f;
|
||||
setPos(x, y, z);
|
||||
field_3C.x = x;
|
||||
field_3C.y = y;
|
||||
field_3C.z = z;
|
||||
m_vel.x = 0.0f;
|
||||
m_vel.y = 0.0f;
|
||||
m_vel.z = 0.0f;
|
||||
|
||||
#if defined(ENH_ALLOW_SAND_GRAVITY)
|
||||
field_C8 = RENDER_FALLING_TILE;
|
||||
#endif
|
||||
}
|
||||
|
||||
float FallingTile::getShadowHeightOffs()
|
||||
{
|
||||
return 0.0f;
|
||||
}
|
||||
|
||||
bool FallingTile::isPickable()
|
||||
{
|
||||
return !m_bRemoved;
|
||||
}
|
||||
|
||||
void FallingTile::tick()
|
||||
{
|
||||
if (!m_id)
|
||||
remove();
|
||||
|
||||
field_3C = m_pos;
|
||||
field_E0++;
|
||||
|
||||
m_vel.y -= 0.04f;
|
||||
move(m_vel.x, m_vel.y, m_vel.z);
|
||||
|
||||
m_vel *= 0.98f;
|
||||
|
||||
int tileX = Mth::floor(m_pos.x);
|
||||
int tileY = Mth::floor(m_pos.y);
|
||||
int tileZ = Mth::floor(m_pos.z);
|
||||
|
||||
// if we're inside one of our own tiles, clear it.
|
||||
// Assumes we started there
|
||||
if (m_pLevel->getTile(tileX, tileY, tileZ) == m_id)
|
||||
m_pLevel->setTile(tileX, tileY, tileZ, TILE_AIR);
|
||||
|
||||
if (!field_7C)
|
||||
{
|
||||
if (field_E0 > 100 && !m_pLevel->field_11)
|
||||
remove();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
m_vel.x *= 0.7f;
|
||||
m_vel.z *= 0.7f;
|
||||
m_vel.y *= -0.5f;
|
||||
remove();
|
||||
if (m_pLevel->mayPlace(m_id, tileX, tileY, tileZ, true))
|
||||
{
|
||||
m_pLevel->setTile(tileX, tileY, tileZ, m_id);
|
||||
}
|
||||
else
|
||||
{
|
||||
// @TODO: spawn resources?
|
||||
}
|
||||
}
|
||||
|
||||
Level* FallingTile::getLevel()
|
||||
{
|
||||
return m_pLevel;
|
||||
}
|
||||
21
source/World/Entity/FallingTile.hpp
Normal file
21
source/World/Entity/FallingTile.hpp
Normal file
@@ -0,0 +1,21 @@
|
||||
#pragma once
|
||||
|
||||
#include "Entity.hpp"
|
||||
|
||||
class FallingTile : public Entity
|
||||
{
|
||||
public:
|
||||
FallingTile(Level*);
|
||||
FallingTile(Level*, float x, float y, float z, int id);
|
||||
|
||||
float getShadowHeightOffs() override;
|
||||
bool isPickable() override;
|
||||
void tick() override;
|
||||
|
||||
Level* getLevel();
|
||||
|
||||
public:
|
||||
int m_id;
|
||||
int field_E0 = 0;
|
||||
};
|
||||
|
||||
166
source/World/Entity/ItemEntity.cpp
Normal file
166
source/World/Entity/ItemEntity.cpp
Normal file
@@ -0,0 +1,166 @@
|
||||
#include "ItemEntity.hpp"
|
||||
#include "Level.hpp"
|
||||
|
||||
ItemEntity::ItemEntity(Level* level) : Entity(level)
|
||||
#ifndef ORIGINAL_CODE
|
||||
, m__itemInstance(0, 0, 0)
|
||||
#endif
|
||||
{
|
||||
// @NOTE: not setting render type
|
||||
field_E8 = 2 * float(M_PI) * Mth::random();
|
||||
setSize(0.25f, 0.25f);
|
||||
field_84 = field_8C * 0.5f;
|
||||
}
|
||||
|
||||
ItemEntity::ItemEntity(Level* level, float x, float y, float z, ItemInstance* itemInstance) :
|
||||
Entity(level)
|
||||
#ifndef ORIGINAL_CODE
|
||||
, m__itemInstance(0, 0, 0)
|
||||
#endif
|
||||
{
|
||||
field_C8 = RENDER_ITEM;
|
||||
field_E8 = 2 * float(M_PI) * Mth::random();
|
||||
setSize(0.25f, 0.25f);
|
||||
field_84 = field_8C * 0.5f;
|
||||
setPos(x, y, z);
|
||||
|
||||
// @BUG: Keeping a pointer to the original ItemInstance may end up storing an invalid one
|
||||
#ifdef ORIGINAL_CODE
|
||||
m_pItemInstance = itemInstance;
|
||||
#else
|
||||
// copy it
|
||||
m__itemInstance = *itemInstance;
|
||||
#endif
|
||||
|
||||
m_yaw = 360.0f * Mth::random();
|
||||
|
||||
m_vel.y = 0.2f;
|
||||
m_vel.x = Mth::random() * 0.2f - 0.1f;
|
||||
m_vel.z = Mth::random() * 0.2f - 0.1f;
|
||||
}
|
||||
|
||||
void ItemEntity::burn(int damage)
|
||||
{
|
||||
hurt(nullptr, damage);
|
||||
}
|
||||
|
||||
bool ItemEntity::hurt(Entity* pCulprit, int damage)
|
||||
{
|
||||
markHurt();
|
||||
m_health -= damage;
|
||||
if (m_health < 0)
|
||||
remove();
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool ItemEntity::isInWater()
|
||||
{
|
||||
return m_pLevel->checkAndHandleWater(m_hitbox, Material::water, this);
|
||||
}
|
||||
|
||||
void ItemEntity::playerTouch(Player* player)
|
||||
{
|
||||
// Here, this would give the item to the player, and remove the item entity.
|
||||
#ifdef TEST_DROPPED_ITEMS
|
||||
if (field_E4 != 0)
|
||||
return;
|
||||
|
||||
// No inventory to add an item to. Just set the amount to 0
|
||||
m_pItemInstance->m_amount = 0;
|
||||
|
||||
// No "random.pop" sound.
|
||||
|
||||
if (m_pItemInstance->m_amount <= 0)
|
||||
remove();
|
||||
#endif
|
||||
}
|
||||
|
||||
void ItemEntity::tick()
|
||||
{
|
||||
Entity::tick();
|
||||
|
||||
if (field_E4 > 0)
|
||||
field_E4--;
|
||||
|
||||
field_3C = m_pos;
|
||||
m_vel.y -= 0.04f;
|
||||
|
||||
if (m_pLevel->getMaterial(Mth::floor(m_pos.x), Mth::floor(m_pos.y), Mth::floor(m_pos.z)) == Material::lava)
|
||||
{
|
||||
// give it a small bounce upwards
|
||||
m_vel.y = 0.2f;
|
||||
m_vel.x = 0.2f * (sharedRandom.nextFloat() - sharedRandom.nextFloat());
|
||||
m_vel.z = 0.2f * (sharedRandom.nextFloat() - sharedRandom.nextFloat());
|
||||
}
|
||||
|
||||
checkInTile(m_pos.x, m_pos.y, m_pos.z);
|
||||
|
||||
move(m_vel.x, m_vel.y, m_vel.z);
|
||||
|
||||
float dragFactor = 0.98f;
|
||||
|
||||
if (field_7C)
|
||||
{
|
||||
dragFactor = 0.588f;
|
||||
TileID tile = m_pLevel->getTile(Mth::floor(m_pos.x), Mth::floor(m_hitbox.min.y) - 1, Mth::floor(m_pos.z));
|
||||
if (tile > 0)
|
||||
dragFactor = Tile::tiles[tile]->field_30 * 0.98f;
|
||||
}
|
||||
|
||||
m_vel.x *= dragFactor;
|
||||
m_vel.z *= dragFactor;
|
||||
m_vel.y *= 0.98f;
|
||||
|
||||
if (field_7C)
|
||||
m_vel.y *= -0.5f;
|
||||
|
||||
field_EC++;
|
||||
field_E0++;
|
||||
|
||||
//despawn after 5 minutes
|
||||
if (field_E0 >= 6000)
|
||||
remove();
|
||||
}
|
||||
|
||||
void ItemEntity::checkInTile(float x, float y, float z)
|
||||
{
|
||||
int xfl = Mth::floor(x);
|
||||
int yfl = Mth::floor(y);
|
||||
int zfl = Mth::floor(z);
|
||||
|
||||
if (!Tile::solid[m_pLevel->getTile(xfl, yfl, zfl)])
|
||||
return;
|
||||
|
||||
bool solidXN = Tile::solid[m_pLevel->getTile(xfl - 1, yfl, zfl)];
|
||||
bool solidXP = Tile::solid[m_pLevel->getTile(xfl + 1, yfl, zfl)];
|
||||
bool solidYN = Tile::solid[m_pLevel->getTile(xfl, yfl - 1, zfl)];
|
||||
bool solidYP = Tile::solid[m_pLevel->getTile(xfl, yfl + 1, zfl)];
|
||||
bool solidZN = Tile::solid[m_pLevel->getTile(xfl, yfl, zfl - 1)];
|
||||
bool solidZP = Tile::solid[m_pLevel->getTile(xfl, yfl, zfl + 1)];
|
||||
|
||||
float mindist = 9999.0f;
|
||||
int mindir = -1;
|
||||
|
||||
float xdiff = x - float(xfl);
|
||||
float ydiff = y - float(yfl);
|
||||
float zdiff = z - float(zfl);
|
||||
if (!solidXN && xdiff < mindist) mindist = xdiff, mindir = 0;
|
||||
if (!solidXP && 1.0f - xdiff < mindist) mindist = 1.0f - xdiff, mindir = 1;
|
||||
if (!solidYN && ydiff < mindist) mindist = ydiff, mindir = 2;
|
||||
if (!solidYP && 1.0f - ydiff < mindist) mindist = 1.0f - ydiff, mindir = 3;
|
||||
if (!solidZN && zdiff < mindist) mindist = zdiff, mindir = 4;
|
||||
if (!solidZP && 1.0f - zdiff < mindist) mindist = 1.0f - zdiff, mindir = 5;
|
||||
|
||||
// the -1 case will be handled accordingly
|
||||
float force = 0.1f + 0.2f * sharedRandom.nextFloat();
|
||||
switch (mindir)
|
||||
{
|
||||
case 0: m_vel.x = -force; break;
|
||||
case 1: m_vel.x = force; break;
|
||||
case 2: m_vel.y = -force; break;
|
||||
case 3: m_vel.y = force; break;
|
||||
case 4: m_vel.z = -force; break;
|
||||
case 5: m_vel.z = force; break;
|
||||
}
|
||||
}
|
||||
35
source/World/Entity/ItemEntity.hpp
Normal file
35
source/World/Entity/ItemEntity.hpp
Normal file
@@ -0,0 +1,35 @@
|
||||
#pragma once
|
||||
|
||||
#include "Entity.hpp"
|
||||
|
||||
class ItemEntity : public Entity
|
||||
{
|
||||
public:
|
||||
ItemEntity(Level* level);
|
||||
ItemEntity(Level* level, float x, float y, float z, ItemInstance* itemInstance);
|
||||
|
||||
void burn(int damage) override;
|
||||
bool hurt(Entity* pCulprit, int damage) override;
|
||||
bool isInWater() override;
|
||||
void playerTouch(Player*) override;
|
||||
void tick() override;
|
||||
|
||||
void checkInTile(float x, float y, float z);
|
||||
|
||||
public:
|
||||
// @NOTE: The original code keeps a pointer to something which is not duplicated with a new(), nor does it delete() the instance.
|
||||
// So either it's leaked, or the code will use invalid memory.
|
||||
#ifdef ORIGINAL_CODE
|
||||
ItemInstance* m_pItemInstance;
|
||||
#else
|
||||
ItemInstance m__itemInstance;
|
||||
ItemInstance* m_pItemInstance = &m__itemInstance;
|
||||
#endif
|
||||
|
||||
int field_E0 = 0;
|
||||
int field_E4 = 0;
|
||||
float field_E8 = 0.0f;
|
||||
int field_EC = 0;
|
||||
int m_health = 5;
|
||||
};
|
||||
|
||||
206
source/World/Entity/LocalPlayer.cpp
Normal file
206
source/World/Entity/LocalPlayer.cpp
Normal file
@@ -0,0 +1,206 @@
|
||||
#include "LocalPlayer.hpp"
|
||||
#include "Minecraft.hpp"
|
||||
|
||||
int dword_250ADC, dword_250AE0;
|
||||
|
||||
LocalPlayer::LocalPlayer(Minecraft* pMinecraft, Level* pLevel, User* pUser, int i) : Player(pLevel)
|
||||
{
|
||||
m_pMinecraft = pMinecraft;
|
||||
m_name = pUser->field_0;
|
||||
|
||||
field_BC4 = i;
|
||||
field_C38 = m_pInventory->getSelectedItemId();
|
||||
}
|
||||
|
||||
LocalPlayer::~LocalPlayer()
|
||||
{
|
||||
if (m_pKeyboardInput)
|
||||
delete m_pKeyboardInput;
|
||||
}
|
||||
|
||||
void LocalPlayer::aiStep()
|
||||
{
|
||||
m_pKeyboardInput->tick(/* this */);
|
||||
if (m_pKeyboardInput->m_bSneakButton && field_A4 < 0.2f)
|
||||
{
|
||||
field_A4 = 0.2f;
|
||||
}
|
||||
|
||||
Mob::aiStep();
|
||||
Player::aiStep();
|
||||
}
|
||||
|
||||
void LocalPlayer::animateRespawn()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void LocalPlayer::calculateFlight(float x, float y, float z)
|
||||
{
|
||||
float f1 = m_pMinecraft->m_options.field_244;
|
||||
float x1 = f1 * x;
|
||||
float z1 = f1 * z;
|
||||
|
||||
float y1 = 0.0f;
|
||||
if (Keyboard::_states[AKEYCODE_BUTTON_R1] == 1)
|
||||
y1 = f1 * 0.2f;
|
||||
if (Keyboard::_states[AKEYCODE_BUTTON_L1] == 1)
|
||||
y1 = f1 * -0.2f;
|
||||
|
||||
field_BFC += x1;
|
||||
float f2 = m_pMinecraft->m_options.field_8 * 0.35f;
|
||||
float f3 = f2 * (field_BFC - field_C00);
|
||||
float f4 = field_C04 + 0.5f * (f3 - field_C04);
|
||||
field_C04 = f4;
|
||||
if ((f3 <= 0.0f || f3 <= f4) && (f3 >= 0.0f || f3 >= f4))
|
||||
f4 = f3;
|
||||
field_C00 += f4;
|
||||
field_BF0 = f4 * 10.0f;
|
||||
|
||||
field_C08 += y1;
|
||||
float f5 = f2 * (field_C08 - field_C0C);
|
||||
float f6 = field_C10 + 0.5f * (f5 - field_C10);
|
||||
field_C10 = f6;
|
||||
if ((f5 <= 0.0f || f5 <= f6) && (f5 >= 0.0f || f5 >= f6))
|
||||
f6 = f5;
|
||||
field_C0C += f6;
|
||||
field_BF4 = f6 * 10.0f;
|
||||
|
||||
field_C14 += z1;
|
||||
float f7 = f2 * (field_C14 - field_C18);
|
||||
float f8 = field_C1C + 0.5f * (f7 - field_C1C);
|
||||
field_C1C = f8;
|
||||
if ((f7 <= 0.0f || f7 <= f8) && (f7 >= 0.0f || f7 >= f8))
|
||||
f8 = f7;
|
||||
field_C18 += f8;
|
||||
field_BF8 = f8 * 10.0f;
|
||||
}
|
||||
|
||||
void LocalPlayer::closeContainer()
|
||||
{
|
||||
Player::closeContainer();
|
||||
m_pMinecraft->setScreen(nullptr);
|
||||
}
|
||||
|
||||
bool LocalPlayer::isSneaking()
|
||||
{
|
||||
return m_pKeyboardInput->m_bSneakButton;
|
||||
}
|
||||
|
||||
int LocalPlayer::move(float x, float y, float z)
|
||||
{
|
||||
int result = 0;
|
||||
|
||||
LocalPlayer* pLP = m_pMinecraft->m_pLocalPlayer;
|
||||
if (Minecraft::DEADMAU5_CAMERA_CHEATS && pLP == this && m_pMinecraft->m_options.m_bFlyCheat)
|
||||
{
|
||||
//@HUH: Using m_pMinecraft->m_pLocalPlayer instead of this, even though they're the same
|
||||
pLP->m_bNoCollision = true;
|
||||
|
||||
float field_94_old = field_94;
|
||||
|
||||
pLP->calculateFlight(x, y, z);
|
||||
pLP->m_distanceFallen = 0.0f;
|
||||
pLP->m_vel.y = 0.0f;
|
||||
|
||||
// This looks very funny.
|
||||
result = pLP->Entity::move(field_BF0, field_BF4, field_BF8);
|
||||
|
||||
pLP->field_7C = true;
|
||||
|
||||
field_94 = field_94_old;
|
||||
}
|
||||
else
|
||||
{
|
||||
#ifndef ORIGINAL_CODE
|
||||
// @BUG: In the original Minecraft, you can't stop flying! If you do, you'll just fall through to the bottom of the world. :(
|
||||
pLP->m_bNoCollision = false;
|
||||
#endif
|
||||
|
||||
// autojump stuff
|
||||
if (m_nAutoJumpFrames > 0)
|
||||
{
|
||||
m_nAutoJumpFrames--;
|
||||
m_pKeyboardInput->m_bJumpButton = true;
|
||||
}
|
||||
|
||||
float posX = m_pos.x;
|
||||
float posY = m_pos.y;
|
||||
|
||||
result = Entity::move(x, y, z);
|
||||
|
||||
//@BUG: backing up posZ too late
|
||||
float posZ = m_pos.z;
|
||||
|
||||
if (m_nAutoJumpFrames <= 0)
|
||||
{
|
||||
if (Mth::floor(posX * 2) == Mth::floor(m_pos.x * 2) &&
|
||||
Mth::floor(posY * 2) == Mth::floor(m_pos.y * 2) &&
|
||||
Mth::floor(posZ * 2) == Mth::floor(m_pos.z * 2))
|
||||
return result;
|
||||
|
||||
float dist = Mth::sqrt(x * x + z * z);
|
||||
int x1 = Mth::floor(x / dist + m_pos.x);
|
||||
int z1 = Mth::floor(z / dist + m_pos.z);
|
||||
|
||||
TileID tileOnTop = m_pLevel->getTile(x1, int(m_pos.y - 1.0f), z1);
|
||||
|
||||
// not standing on top of a tile?
|
||||
if (!m_pLevel->isSolidTile(x1, int(m_pos.y - 1.0f), z1))
|
||||
return 0;
|
||||
|
||||
// aren't inside of a tile right now
|
||||
if (m_pLevel->isSolidTile(x1, int(m_pos.y), z1))
|
||||
return 0;
|
||||
|
||||
// don't have anything on top of us
|
||||
if (m_pLevel->isSolidTile(x1, int(m_pos.y + 1.0f), z1))
|
||||
return 1;
|
||||
|
||||
// are we trying to walk into stairs or a slab?
|
||||
if (tileOnTop != Tile::stairs_stone->m_ID && tileOnTop != Tile::stairs_wood->m_ID && tileOnTop != Tile::stoneSlabHalf->m_ID)
|
||||
// Nope, we're walking towards a full block. Trigger an auto jump.
|
||||
m_nAutoJumpFrames = 1;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void LocalPlayer::tick()
|
||||
{
|
||||
Player::tick();
|
||||
|
||||
if (m_pMinecraft->isOnline())
|
||||
{
|
||||
if (fabsf(m_pos.x - field_C24) > 0.1f ||
|
||||
fabsf(m_pos.y - field_C28) > 0.01f ||
|
||||
fabsf(m_pos.z - field_C2C) > 0.1f ||
|
||||
fabsf(field_C30 - m_pitch) > 1.0f ||
|
||||
fabsf(field_C34 - m_yaw) > 1.0f)
|
||||
{
|
||||
m_pMinecraft->m_pRakNetInstance->send(new MovePlayerPacket(m_EntityID, m_pos.x, m_pos.y - field_84, m_pos.z, m_pitch, m_yaw));
|
||||
field_C24 = m_pos.x;
|
||||
field_C28 = m_pos.y;
|
||||
field_C2C = m_pos.z;
|
||||
field_C30 = m_pitch;
|
||||
field_C34 = m_yaw;
|
||||
}
|
||||
|
||||
if (field_C38 != m_pInventory->getSelectedItemId())
|
||||
{
|
||||
field_C38 = m_pInventory->getSelectedItemId();
|
||||
m_pMinecraft->m_pRakNetInstance->send(new PlayerEquipmentPacket(m_EntityID, field_C38));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void LocalPlayer::updateAi()
|
||||
{
|
||||
Player::updateAi();
|
||||
|
||||
field_B00 = m_pKeyboardInput->m_horzInput;
|
||||
field_B04 = m_pKeyboardInput->m_vertInput;
|
||||
|
||||
field_B0C = m_pKeyboardInput->m_bJumpButton || m_nAutoJumpFrames > 0;
|
||||
}
|
||||
52
source/World/Entity/LocalPlayer.hpp
Normal file
52
source/World/Entity/LocalPlayer.hpp
Normal file
@@ -0,0 +1,52 @@
|
||||
#pragma once
|
||||
|
||||
#include "Player.hpp"
|
||||
#include "User.hpp"
|
||||
#include "KeyboardInput.hpp"
|
||||
|
||||
class Minecraft;
|
||||
|
||||
class LocalPlayer : public Player
|
||||
{
|
||||
public:
|
||||
LocalPlayer(Minecraft*, Level*, User*, int);
|
||||
virtual ~LocalPlayer();
|
||||
|
||||
// TODO: void addAdditonalSaveData();
|
||||
virtual void animateRespawn() override;
|
||||
virtual void aiStep() override;
|
||||
virtual bool isSneaking() override;
|
||||
virtual int move(float x, float y, float z) override;
|
||||
virtual void tick() override;
|
||||
virtual void updateAi() override;
|
||||
|
||||
void calculateFlight(float, float, float);
|
||||
void closeContainer(); //@HUH: oddly enough not a virtual/override
|
||||
|
||||
|
||||
public:
|
||||
int field_BEC = 0;
|
||||
float field_BF0 = 0.0f;
|
||||
float field_BF4 = 0.0f;
|
||||
float field_BF8 = 0.0f;
|
||||
float field_BFC = 0.0f;
|
||||
float field_C00 = 0.0f;
|
||||
float field_C04 = 0.0f;
|
||||
float field_C08 = 0.0f;
|
||||
float field_C0C = 0.0f;
|
||||
float field_C10 = 0.0f;
|
||||
float field_C14 = 0.0f;
|
||||
float field_C18 = 0.0f;
|
||||
float field_C1C = 0.0f;
|
||||
int m_nAutoJumpFrames = 0;
|
||||
// multiplayer related
|
||||
float field_C24 = 0.0f;
|
||||
float field_C28 = 0.0f;
|
||||
float field_C2C = 0.0f;
|
||||
float field_C30 = 0.0f;
|
||||
float field_C34 = 0.0f;
|
||||
// multiplayer related -- end
|
||||
int field_C38 = 0;
|
||||
Minecraft* m_pMinecraft;
|
||||
KeyboardInput* m_pKeyboardInput = nullptr;
|
||||
};
|
||||
731
source/World/Entity/Mob.cpp
Normal file
731
source/World/Entity/Mob.cpp
Normal file
@@ -0,0 +1,731 @@
|
||||
#include "Mob.hpp"
|
||||
#include "Level.hpp"
|
||||
|
||||
Mob::Mob(Level* pLevel) : Entity(pLevel)
|
||||
{
|
||||
m_texture = "/mob/char.png";
|
||||
m_class = "";
|
||||
|
||||
field_34 = 1;
|
||||
|
||||
field_E4 = (Mth::random() + 1.0f) * 0.01f;
|
||||
setPos(m_pos.x, m_pos.y, m_pos.z);
|
||||
field_E0 = Mth::random() * 12398.0f;
|
||||
m_yaw = float(Mth::random() * M_PI);
|
||||
field_A8 = 0.5f;
|
||||
}
|
||||
|
||||
Mob::~Mob()
|
||||
{
|
||||
}
|
||||
|
||||
void Mob::lerpTo(float x, float y, float z, float yaw, float pitch, int i)
|
||||
{
|
||||
field_B70 = x;
|
||||
field_B74 = y + field_84;
|
||||
field_B78 = z;
|
||||
field_B7C = yaw;
|
||||
field_B80 = pitch;
|
||||
field_B6C = i;
|
||||
}
|
||||
|
||||
void Mob::tick()
|
||||
{
|
||||
superTick();
|
||||
|
||||
if (field_B6C > 0)
|
||||
{
|
||||
float xPos = m_pos.x + (field_B70 - m_pos.x) / field_B6C;
|
||||
float yPos = m_pos.y + (field_B74 - m_pos.y) / field_B6C;
|
||||
float zPos = m_pos.z + (field_B78 - m_pos.z) / field_B6C;
|
||||
|
||||
float ang = field_B7C - m_yaw;
|
||||
while (ang < -180.0f) ang += 360.0f;
|
||||
while (ang >= 180.0f) ang -= 360.0f;
|
||||
|
||||
m_yaw += ang / float(field_B6C);
|
||||
m_pitch += (field_B80 - m_pitch) / float(field_B6C);
|
||||
|
||||
setPos(xPos, yPos, zPos);
|
||||
setRot(m_yaw, m_pitch);
|
||||
|
||||
field_B6C--;
|
||||
}
|
||||
|
||||
aiStep();
|
||||
updateWalkAnim();
|
||||
|
||||
//@TODO: unf*ck this variable mess
|
||||
float deltaX, deltaZ, dist, x1, x2, x3, x4, x5, x6, x7, field_E8_2, field_E8_new, v36;
|
||||
bool angleOOB = false;
|
||||
|
||||
deltaX = m_pos.x - field_3C.x;
|
||||
deltaZ = m_pos.z - field_3C.z;
|
||||
dist = Mth::sqrt(deltaZ * deltaZ + deltaX * deltaX);
|
||||
field_E8_2 = field_E8;
|
||||
x1 = field_E8_2;
|
||||
|
||||
field_B4C = field_B50;
|
||||
|
||||
if (dist > 0.05f)
|
||||
{
|
||||
x2 = dist * 3.0f;
|
||||
v36 = Mth::atan2(deltaZ, deltaX);
|
||||
x3 = 1.0f;
|
||||
x1 = ((v36 * 180.0f) / float(M_PI)) - 90.0f;
|
||||
field_E8_2 = this->field_E8;
|
||||
}
|
||||
else
|
||||
{
|
||||
x3 = 0.0f;
|
||||
x2 = 0.0f;
|
||||
}
|
||||
|
||||
x4 = field_F8;
|
||||
if (x4 <= 0.0f)
|
||||
x4 = m_yaw;
|
||||
else
|
||||
x4 = x1 = m_yaw;
|
||||
|
||||
if (!field_7C)
|
||||
x3 = 0.0f;
|
||||
|
||||
field_B50 += (x3 - field_B50) * 0.3f;
|
||||
|
||||
x5 = x1 - field_E8_2;
|
||||
while (x5 < -180.0f)
|
||||
x5 += 360.0f;
|
||||
while (x5 >= 180.0f)
|
||||
x5 -= 360.0f;
|
||||
|
||||
field_E8_new = field_E8_2 + (float)(x5 * 0.3);
|
||||
this->field_E8 = field_E8_new;
|
||||
|
||||
x6 = x4 - field_E8_new;
|
||||
|
||||
while (x6 < -180.0f)
|
||||
x6 += 360.0f;
|
||||
|
||||
while (x6 >= 180.0f)
|
||||
x6 -= 360.0f;
|
||||
|
||||
angleOOB = x6 < -90.0f || x6 >= 90.0f;
|
||||
|
||||
if (x6 < -75.0f)
|
||||
{
|
||||
x7 = x4 + 75.0f;
|
||||
x6 = -75.0f;
|
||||
field_E8 = x4 + 75.0f;
|
||||
goto LABEL_30;
|
||||
}
|
||||
if (x6 >= 75.0f)
|
||||
{
|
||||
x7 = x4 - 75.0f;
|
||||
x6 = 75.0f;
|
||||
field_E8 = x4 - 75.0f;
|
||||
LABEL_30:
|
||||
field_E8 = x7 + (x6 * 0.2f);
|
||||
goto LABEL_31;
|
||||
}
|
||||
|
||||
x7 = x4 - x6;
|
||||
field_E8 = x4 - x6;
|
||||
if (x6 * x6 > 2500.0f)
|
||||
goto LABEL_30;
|
||||
|
||||
LABEL_31:
|
||||
if (angleOOB)
|
||||
x2 = -x2;
|
||||
|
||||
while (x4 - field_5C < -180.0f)
|
||||
field_5C -= 360.0f;
|
||||
|
||||
while (x4 - field_5C >= 180.0f)
|
||||
field_5C += 360.0f;
|
||||
|
||||
while (field_E8 - field_EC < -180.0f)
|
||||
field_EC -= 360.0f;
|
||||
|
||||
while (field_E8 - field_EC >= 180.0f)
|
||||
field_EC += 360.0f;
|
||||
|
||||
while (m_pitch - field_60 < -180.0f);
|
||||
field_60 -= 360.0f;
|
||||
|
||||
while (m_pitch - field_60 >= 180.0f)
|
||||
field_60 += 360.0f;
|
||||
|
||||
field_B54 += x2;
|
||||
}
|
||||
|
||||
void Mob::baseTick()
|
||||
{
|
||||
field_F4 = field_F8;
|
||||
Entity::baseTick();
|
||||
|
||||
if (isAlive() && isInWall())
|
||||
hurt(nullptr, 1);
|
||||
|
||||
if (isAlive() && isUnderLiquid(Material::water) && !isWaterMob())
|
||||
{
|
||||
field_BC--;
|
||||
if (field_BC == -20)
|
||||
{
|
||||
field_BC = 0;
|
||||
|
||||
for (int i = 0; i < 8; i++)
|
||||
{
|
||||
m_pLevel->addParticle("bubble",
|
||||
m_pos.x + m_random.nextFloat() - m_random.nextFloat(),
|
||||
m_pos.y + m_random.nextFloat() - m_random.nextFloat(),
|
||||
m_pos.z + m_random.nextFloat() - m_random.nextFloat(),
|
||||
m_vel.x, m_vel.y, m_vel.z
|
||||
);
|
||||
}
|
||||
|
||||
hurt(nullptr, 2);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
field_BC = field_D0;
|
||||
}
|
||||
|
||||
field_118 = field_11C;
|
||||
|
||||
if (field_114 > 0) field_114--;
|
||||
if (field_104 > 0) field_104--;
|
||||
if (field_B8 > 0) field_B8--;
|
||||
|
||||
if (m_health <= 0)
|
||||
{
|
||||
field_110++;
|
||||
if (field_110 > 20)
|
||||
{
|
||||
beforeRemove();
|
||||
remove();
|
||||
for (int i = 0; i < 20; i++)
|
||||
{
|
||||
m_pLevel->addParticle("explode",
|
||||
m_pos.x + 2 * field_88 * m_random.nextFloat() - field_88,
|
||||
m_pos.y + field_8C * m_random.nextFloat(),
|
||||
m_pos.z + 2 * field_88 * m_random.nextFloat() - field_88,
|
||||
0.02f * (m_random.nextFloat() * 2 - 1) * (m_random.nextFloat() * 2 - 1),
|
||||
0.02f * (m_random.nextFloat() * 2 - 1) * (m_random.nextFloat() * 2 - 1),
|
||||
0.02f * (m_random.nextFloat() * 2 - 1) * (m_random.nextFloat() * 2 - 1)
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
field_B58 = field_B54;
|
||||
field_EC = field_E8;
|
||||
field_5C = m_yaw;
|
||||
field_60 = m_pitch;
|
||||
}
|
||||
|
||||
float Mob::getHeadHeight()
|
||||
{
|
||||
return 0.85f * field_8C;
|
||||
}
|
||||
|
||||
bool Mob::isPickable()
|
||||
{
|
||||
return !m_bRemoved;
|
||||
}
|
||||
|
||||
bool Mob::isPushable()
|
||||
{
|
||||
return !m_bRemoved;
|
||||
}
|
||||
|
||||
bool Mob::isShootable()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Mob::isAlive()
|
||||
{
|
||||
if (m_bRemoved)
|
||||
return false;
|
||||
|
||||
return m_health >= 0;
|
||||
}
|
||||
|
||||
bool Mob::hurt(Entity *pAttacker, int damage)
|
||||
{
|
||||
if (m_pLevel->field_11)
|
||||
return false;
|
||||
|
||||
field_AFC = m_pLevel->field_11;
|
||||
|
||||
if (m_health <= 0)
|
||||
return false;
|
||||
|
||||
field_12C = 1.5f;
|
||||
if (float(field_B8) <= float(field_DC) * 0.5f)
|
||||
{
|
||||
field_100 = m_health;
|
||||
field_B8 = field_DC;
|
||||
field_B84 = damage;
|
||||
actuallyHurt(damage);
|
||||
field_108 = 10;
|
||||
field_104 = 10;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (field_B84 >= damage)
|
||||
return 0;
|
||||
|
||||
actuallyHurt(damage - field_B84);
|
||||
field_B84 = damage;
|
||||
}
|
||||
|
||||
field_10C = 0;
|
||||
if (m_health <= 0)
|
||||
die(pAttacker);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void Mob::animateHurt()
|
||||
{
|
||||
field_108 = 10;
|
||||
field_10C = 0;
|
||||
field_104 = 10;
|
||||
}
|
||||
|
||||
void Mob::setSize(float rad, float height)
|
||||
{
|
||||
Entity::setSize(rad, height);
|
||||
}
|
||||
|
||||
void Mob::outOfWorld()
|
||||
{
|
||||
hurt(nullptr, 4);
|
||||
}
|
||||
|
||||
void Mob::causeFallDamage(float level)
|
||||
{
|
||||
int x = int(ceilf(level - 3));
|
||||
if (x > 0)
|
||||
{
|
||||
hurt(nullptr, 3);
|
||||
|
||||
//@HUH: useless call to getTile? or could this be a return value of some sort
|
||||
//Entity::causeFallDamage returns nothing though, so....
|
||||
m_pLevel->getTile(Mth::floor(m_pos.x), Mth::floor(m_pos.y - 0.2f - field_84), Mth::floor(m_pos.z));
|
||||
}
|
||||
}
|
||||
|
||||
void Mob::knockback(Entity* pEnt, int a, float x, float z)
|
||||
{
|
||||
float power = Mth::invSqrt(x * x + z * z);
|
||||
|
||||
m_vel.x = m_vel.x * 0.5f - x * power * 0.4f;
|
||||
m_vel.y = m_vel.y * 0.5f + 0.4f;
|
||||
m_vel.z = m_vel.z * 0.5f - z * power * 0.4f;
|
||||
|
||||
//@BUG: maybe this is meant to behave differently.
|
||||
// Unless the player is falling, the Y vel will always be 0.4.
|
||||
if (m_vel.y > 0.4f)
|
||||
m_vel.y = 0.4f;
|
||||
}
|
||||
|
||||
bool Mob::onLadder()
|
||||
{
|
||||
int tileX = Mth::floor(m_pos.x);
|
||||
int tileZ = Mth::floor(m_pos.z);
|
||||
int tileY = Mth::floor(m_hitbox.min.y);
|
||||
|
||||
//@INFO: Pre Beta 1.5 stair behaviour
|
||||
return
|
||||
m_pLevel->getTile(tileX, tileY + 0, tileZ) == Tile::ladder->m_ID ||
|
||||
m_pLevel->getTile(tileX, tileY + 1, tileZ) == Tile::ladder->m_ID;
|
||||
}
|
||||
|
||||
void Mob::spawnAnim()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
std::string Mob::getTexture()
|
||||
{
|
||||
return m_texture;
|
||||
}
|
||||
|
||||
void Mob::playAmbientSound()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
int Mob::getAmbientSoundInterval()
|
||||
{
|
||||
return 80;
|
||||
}
|
||||
|
||||
void Mob::heal(int health)
|
||||
{
|
||||
if (m_health <= 0)
|
||||
return;
|
||||
|
||||
m_health += health;
|
||||
if (m_health > C_MAX_MOB_HEALTH)
|
||||
m_health = C_MAX_MOB_HEALTH;
|
||||
|
||||
field_B8 = field_DC / 2;
|
||||
}
|
||||
|
||||
HitResult Mob::pick(float f1, float f2)
|
||||
{
|
||||
Vec3 pos = getPos(f2);
|
||||
Vec3 view = getViewVector(f2);
|
||||
|
||||
Vec3 limit = pos + view * f1;
|
||||
return m_pLevel->clip(pos, limit);
|
||||
}
|
||||
|
||||
void Mob::travel(float a2, float a3)
|
||||
{
|
||||
float x1, x2, dragFactor, oldYPos = m_pos.y;
|
||||
if (isInWater())
|
||||
{
|
||||
moveRelative(a2, a3, 0.02f);
|
||||
move(m_vel.x, m_vel.y, m_vel.z);
|
||||
x1 = 0.8f;
|
||||
goto label_3;
|
||||
}
|
||||
if (isInLava())
|
||||
{
|
||||
moveRelative(a2, a3, 0.02f);
|
||||
move(m_vel.x, m_vel.y, m_vel.z);
|
||||
x1 = 0.5f;
|
||||
label_3:
|
||||
|
||||
m_vel.y = m_vel.y * x1 - 0.02f;
|
||||
m_vel.x *= x1;
|
||||
m_vel.z *= x1;
|
||||
|
||||
if (field_7D)
|
||||
{
|
||||
if (isFree(m_vel.x, m_vel.y + 0.6f - m_pos.y + oldYPos, m_vel.z))
|
||||
m_vel.y = 0.3f;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (!field_7C)
|
||||
{
|
||||
x2 = 0.02f;
|
||||
}
|
||||
else
|
||||
{
|
||||
float _x1;
|
||||
int tileX = Mth::floor(m_pos.x);
|
||||
int tileY = Mth::floor(m_hitbox.min.y);
|
||||
int tileZ = Mth::floor(m_pos.z);
|
||||
TileID tile = m_pLevel->getTile(tileX, tileY - 1, tileZ);
|
||||
if (tile <= 0)
|
||||
_x1 = 0.546f;
|
||||
else
|
||||
_x1 = Tile::tiles[tile]->field_30 * 0.91f;
|
||||
|
||||
assert(_x1 != 0.0f);
|
||||
|
||||
x2 = (0.16277f / (_x1 * _x1 * _x1)) * 0.1f;
|
||||
}
|
||||
|
||||
moveRelative(a2, a3, x2);
|
||||
|
||||
if (!field_7C)
|
||||
{
|
||||
dragFactor = 0.91f;
|
||||
}
|
||||
else
|
||||
{
|
||||
//@HUH: repeated code. Could be an inlined function?
|
||||
int tileX = Mth::floor(m_pos.x);
|
||||
int tileY = Mth::floor(m_hitbox.min.y);
|
||||
int tileZ = Mth::floor(m_pos.z);
|
||||
TileID tile = m_pLevel->getTile(tileX, tileY - 1, tileZ);
|
||||
if (tile <= 0)
|
||||
dragFactor = 0.546f;
|
||||
else
|
||||
dragFactor = Tile::tiles[tile]->field_30 * 0.91f;
|
||||
}
|
||||
|
||||
if (onLadder())
|
||||
{
|
||||
|
||||
m_distanceFallen = 0.0f;
|
||||
|
||||
if (m_vel.y < -0.15f)
|
||||
m_vel.y = -0.15f;
|
||||
|
||||
if (isSneaking() && m_vel.y < 0)
|
||||
m_vel.y = 0;
|
||||
}
|
||||
|
||||
move(m_vel.x, m_vel.y, m_vel.z);
|
||||
|
||||
if (field_7D && onLadder())
|
||||
m_vel.y = 0.2f;
|
||||
|
||||
m_vel.y = (m_vel.y - 0.08f) * 0.98f; // gravity?
|
||||
|
||||
// drag
|
||||
m_vel.x *= dragFactor;
|
||||
m_vel.z *= dragFactor;
|
||||
}
|
||||
|
||||
void Mob::die(Entity* pCulprit)
|
||||
{
|
||||
if (pCulprit && field_B48 > 0)
|
||||
pCulprit->awardKillScore(pCulprit, field_B48);
|
||||
|
||||
field_B69 = true;
|
||||
|
||||
if (!m_pLevel->field_11)
|
||||
dropDeathLoot();
|
||||
}
|
||||
|
||||
bool Mob::canSee(Entity* pEnt)
|
||||
{
|
||||
Vec3 v1 = m_pos;
|
||||
v1.y += getHeadHeight();
|
||||
Vec3 v2 = pEnt->m_pos;
|
||||
v2.y += pEnt->getHeadHeight();
|
||||
|
||||
return m_pLevel->clip(v1, v2).m_hitType == HitResult::NONE;
|
||||
}
|
||||
|
||||
void Mob::updateWalkAnim()
|
||||
{
|
||||
field_128 = field_12C;
|
||||
|
||||
float diffX = m_pos.x - field_3C.x;
|
||||
float diffZ = m_pos.z - field_3C.z;
|
||||
|
||||
float spd = 4.0f * Mth::sqrt(diffX * diffX + diffZ * diffZ);
|
||||
if (spd > 1.0f)
|
||||
spd = 1.0f;
|
||||
|
||||
field_12C += (spd - field_12C) * 0.4f;
|
||||
field_130 += field_12C;
|
||||
}
|
||||
|
||||
void Mob::aiStep()
|
||||
{
|
||||
if (isImmobile())
|
||||
{
|
||||
field_B0C = 0;
|
||||
field_B00 = 0.0f;
|
||||
field_B04 = 0.0f;
|
||||
field_B08 = 0.0f;
|
||||
}
|
||||
else if (!field_F0)
|
||||
{
|
||||
updateAi();
|
||||
}
|
||||
|
||||
bool bIsInWater = isInWater(), bIsInLava = isInLava();
|
||||
if (field_B0C)
|
||||
{
|
||||
if (bIsInWater || bIsInLava)
|
||||
m_vel.y += 0.04f;
|
||||
else if (field_7C)
|
||||
jumpFromGround();
|
||||
}
|
||||
|
||||
field_B00 *= 0.98f;
|
||||
field_B04 *= 0.98f;
|
||||
field_B08 *= 0.9f;
|
||||
|
||||
travel(field_B00, field_B04);
|
||||
|
||||
AABB aabb = m_hitbox;
|
||||
aabb.grow(0.2f, 0.2f, 0.2f);
|
||||
|
||||
auto pEnts = m_pLevel->getEntities(this, aabb);
|
||||
for (auto pEnt : *pEnts)
|
||||
{
|
||||
if (pEnt->isPushable())
|
||||
pEnt->push(this);
|
||||
}
|
||||
}
|
||||
|
||||
bool Mob::isWaterMob()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
void Mob::superTick()
|
||||
{
|
||||
Entity::tick();
|
||||
}
|
||||
|
||||
void Mob::lookAt(Entity* pEnt, float a3, float a4)
|
||||
{
|
||||
float diffX = pEnt->m_pos.x - m_pos.x;
|
||||
float diffZ = pEnt->m_pos.z - m_pos.z;
|
||||
|
||||
float x1 = atan2f(diffZ, diffX);
|
||||
float x2 = atan2f((pEnt->m_hitbox.min.y + pEnt->m_hitbox.max.y) / 2 - m_pos.y - getHeadHeight(), Mth::sqrt(diffX * diffX + diffZ * diffZ));
|
||||
|
||||
m_pitch = -rotlerp(m_pitch, x2 * 180.0f / float(M_PI), a4);
|
||||
m_yaw = rotlerp(m_yaw, x1 * 180.0f / float(M_PI) - 90.0f, a3);
|
||||
}
|
||||
|
||||
bool Mob::isLookingAtAnEntity()
|
||||
{
|
||||
return m_pEntLookedAt != nullptr;
|
||||
}
|
||||
|
||||
Entity* Mob::getLookingAt()
|
||||
{
|
||||
return m_pEntLookedAt;
|
||||
}
|
||||
|
||||
void Mob::beforeRemove()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
bool Mob::canSpawn()
|
||||
{
|
||||
return m_pLevel->getCubes(this, m_hitbox)->empty();
|
||||
}
|
||||
|
||||
float Mob::getAttackAnim(float f)
|
||||
{
|
||||
float x = field_F8 - field_F4;
|
||||
|
||||
if (x < 0.0f)
|
||||
x += 1.0f;
|
||||
|
||||
return field_F4 + (x * f);
|
||||
}
|
||||
|
||||
Vec3 Mob::getPos(float f)
|
||||
{
|
||||
if (f == 1.0f)
|
||||
return m_pos;
|
||||
|
||||
return Vec3(
|
||||
Lerp(field_3C.x, m_pos.x, f),
|
||||
Lerp(field_3C.y, m_pos.y, f),
|
||||
Lerp(field_3C.z, m_pos.z, f)
|
||||
);
|
||||
}
|
||||
|
||||
Vec3 Mob::getLookAngle(float f)
|
||||
{
|
||||
return getViewVector(1.0f);
|
||||
}
|
||||
|
||||
Vec3 Mob::getViewVector(float f)
|
||||
{
|
||||
constexpr float C_180_OVER_PI = 0.017453f;
|
||||
constexpr float C_PI = 3.1416f;
|
||||
|
||||
if (f == 1.0)
|
||||
{
|
||||
float x1 = Mth::cos(-(m_yaw * C_180_OVER_PI) - C_PI);
|
||||
float x2 = Mth::sin(-(m_yaw * C_180_OVER_PI) - C_PI);
|
||||
float x3 = -Mth::cos(-(m_pitch * C_180_OVER_PI));
|
||||
|
||||
return Vec3(x1 * x3, Mth::sin(-(m_pitch * C_180_OVER_PI)), x2 * x3);
|
||||
}
|
||||
|
||||
float x1 = field_60 + (m_pitch - field_60) * f;
|
||||
float x2 = -((field_5C + (m_yaw - field_5C) * f) * C_180_OVER_PI) - C_PI;
|
||||
float x3 = Mth::cos(x2);
|
||||
float x4 = Mth::sin(x2);
|
||||
float x5 = -(x1 * C_180_OVER_PI);
|
||||
float x6 = -Mth::cos(x5);
|
||||
|
||||
return Vec3(x4 * x6, Mth::sin(x5), x3 * x6);
|
||||
}
|
||||
|
||||
int Mob::getMaxSpawnClusterSize()
|
||||
{
|
||||
return 4;
|
||||
}
|
||||
|
||||
void Mob::actuallyHurt(int damage)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
bool Mob::removeWhenFarAway()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
int Mob::getDeathLoot()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
void Mob::dropDeathLoot()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
bool Mob::isImmobile()
|
||||
{
|
||||
return m_health <= 0;
|
||||
}
|
||||
|
||||
void Mob::jumpFromGround()
|
||||
{
|
||||
m_vel.y = 0.42f;
|
||||
}
|
||||
|
||||
void Mob::updateAi()
|
||||
{
|
||||
// TODO
|
||||
}
|
||||
|
||||
int Mob::getMaxHeadXRot()
|
||||
{
|
||||
return 10;
|
||||
}
|
||||
|
||||
float Mob::getSoundVolume()
|
||||
{
|
||||
return 1.0f;
|
||||
}
|
||||
|
||||
std::string Mob::getAmbientSound()
|
||||
{
|
||||
return "";
|
||||
}
|
||||
|
||||
std::string Mob::getHurtSound()
|
||||
{
|
||||
return "random.hurt";
|
||||
}
|
||||
|
||||
std::string Mob::getDeathSound()
|
||||
{
|
||||
return "random.hurt";
|
||||
}
|
||||
|
||||
void Mob::defineSynchedData()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
float Mob::rotlerp(float a2, float a3, float a4)
|
||||
{
|
||||
float ang = a3 - a2;
|
||||
while (ang < -180.0f) ang += 360.0f;
|
||||
while (ang >= 180.0f) ang -= 360.0f;
|
||||
if (ang > a4)
|
||||
ang = a4;
|
||||
if (ang < -a4)
|
||||
ang = -a4;
|
||||
return a2 + ang;
|
||||
}
|
||||
123
source/World/Entity/Mob.hpp
Normal file
123
source/World/Entity/Mob.hpp
Normal file
@@ -0,0 +1,123 @@
|
||||
#pragma once
|
||||
|
||||
#include "Entity.hpp"
|
||||
|
||||
#define C_MAX_MOB_HEALTH (20)
|
||||
|
||||
class Mob : public Entity
|
||||
{
|
||||
public:
|
||||
Mob(Level* pLevel);
|
||||
virtual ~Mob();
|
||||
|
||||
//overrides
|
||||
virtual void lerpTo(float x, float y, float z, float yaw, float pitch, int i) override;
|
||||
virtual void tick() override;
|
||||
virtual void baseTick() override;
|
||||
virtual float getHeadHeight() override;
|
||||
virtual bool isPickable() override;
|
||||
virtual bool isPushable() override;
|
||||
virtual bool isShootable() override;
|
||||
virtual bool isAlive() override;
|
||||
virtual bool hurt(Entity*, int) override;
|
||||
virtual void animateHurt() override;
|
||||
virtual void setSize(float rad, float height) override;
|
||||
virtual void outOfWorld() override;
|
||||
virtual void causeFallDamage(float level) override;
|
||||
|
||||
//virtuals
|
||||
virtual void knockback(Entity* pEnt, int a, float x, float z);
|
||||
virtual void die(Entity* pCulprit);
|
||||
virtual bool canSee(Entity* pEnt);
|
||||
virtual bool onLadder();
|
||||
virtual void spawnAnim();
|
||||
virtual std::string getTexture();
|
||||
virtual bool isWaterMob();
|
||||
virtual void playAmbientSound();
|
||||
virtual int getAmbientSoundInterval();
|
||||
virtual void superTick();
|
||||
virtual void heal(int health);
|
||||
virtual HitResult pick(float, float);
|
||||
virtual void travel(float, float);
|
||||
virtual void updateWalkAnim();
|
||||
virtual void aiStep();
|
||||
//AddAdditonalSaveData TODO
|
||||
//ReadAdditionalSaveData TODO
|
||||
virtual void lookAt(Entity* pEnt, float, float);
|
||||
virtual bool isLookingAtAnEntity();
|
||||
virtual Entity* getLookingAt();
|
||||
virtual void beforeRemove();
|
||||
virtual bool canSpawn();
|
||||
virtual float getAttackAnim(float f);
|
||||
virtual Vec3 getPos(float f);
|
||||
virtual Vec3 getLookAngle(float f);
|
||||
virtual Vec3 getViewVector(float f);
|
||||
virtual int getMaxSpawnClusterSize();
|
||||
virtual void actuallyHurt(int damage);
|
||||
virtual bool removeWhenFarAway();
|
||||
virtual int getDeathLoot();
|
||||
virtual void dropDeathLoot();
|
||||
virtual bool isImmobile();
|
||||
virtual void jumpFromGround();
|
||||
virtual void updateAi();
|
||||
virtual int getMaxHeadXRot();
|
||||
virtual float getSoundVolume();
|
||||
virtual std::string getAmbientSound();
|
||||
virtual std::string getHurtSound();
|
||||
virtual std::string getDeathSound();
|
||||
virtual void defineSynchedData();
|
||||
|
||||
float rotlerp(float, float, float);
|
||||
|
||||
public:
|
||||
int field_DC = 10;
|
||||
float field_E0;
|
||||
float field_E4;
|
||||
float field_E8 = 0.0f;
|
||||
float field_EC = 0.0f;
|
||||
char field_F0 = 0;
|
||||
float field_F4 = 0.0f;
|
||||
float field_F8 = 0.0f;
|
||||
int m_health = 10;
|
||||
int field_100 = 20;
|
||||
int field_104 = 0;
|
||||
int field_108 = 0;
|
||||
float field_10C = 0.0f;
|
||||
int field_110 = 0;
|
||||
int field_114 = 0;
|
||||
float field_118 = 0.0f;
|
||||
float field_11C = 0.0f;
|
||||
int field_120 = 0;
|
||||
int field_124 = 0;
|
||||
float field_128 = 0.0f;
|
||||
float field_12C = 0.0f;
|
||||
float field_130 = 0.0f;
|
||||
Random m_random;
|
||||
int field_AFC = 0;
|
||||
float field_B00 = 0.0f;
|
||||
float field_B04 = 0.0f;
|
||||
float field_B08 = 0.0f;
|
||||
char field_B0C = 0;
|
||||
int field_B10 = 0;
|
||||
float field_B14 = 0.7f;
|
||||
std::string m_texture;
|
||||
std::string m_class;
|
||||
int field_B48 = 0;
|
||||
float field_B4C = 0.0f;
|
||||
float field_B50 = 0.0f;
|
||||
float field_B54 = 0.0f;
|
||||
float field_B58 = 0.0f;
|
||||
float field_B5C = 0.0f;
|
||||
float field_B60 = 1.0f;
|
||||
int field_B64 = 0;
|
||||
char field_B68 = 1;
|
||||
char field_B69 = 0;
|
||||
int field_B6C = 0;
|
||||
float field_B70 = 0.0f;
|
||||
float field_B74 = 0.0f;
|
||||
float field_B78 = 0.0f;
|
||||
float field_B7C = 0.0f;
|
||||
float field_B80 = 0.0f;
|
||||
int field_B84 = 0;
|
||||
Entity* m_pEntLookedAt = nullptr;
|
||||
};
|
||||
260
source/World/Entity/Models/HumanoidModel.cpp
Normal file
260
source/World/Entity/Models/HumanoidModel.cpp
Normal file
@@ -0,0 +1,260 @@
|
||||
#include "HumanoidModel.hpp"
|
||||
#include "Minecraft.hpp"
|
||||
|
||||
HumanoidModel::HumanoidModel(float a, float b):
|
||||
m_head(0, 0),
|
||||
m_body(16, 16),
|
||||
m_armL(40, 16),
|
||||
m_armR(40, 16),
|
||||
m_legL(0, 16),
|
||||
m_legR(0, 16)
|
||||
{
|
||||
m_head.addBox(-4, -8, -4, 8, 8, 8, a);
|
||||
m_head.setPos(0, b, 0);
|
||||
m_body.addBox(-4, 0, -2, 8, 12, 4);
|
||||
m_body.setPos(0, b, 0);
|
||||
m_armL.addBox(-3, -2, -2, 4, 12, 4, a);
|
||||
m_armL.setPos(-5, b + 2, 0);
|
||||
m_armR.field_18 = true;
|
||||
m_armR.addBox(-1, -2, -2, 4, 12, 4, a);
|
||||
m_armR.setPos(5, b + 2, 0);
|
||||
m_legL.addBox(-2, 0, -2, 4, 12, 4, a);
|
||||
m_legL.setPos(-2, b + 12, 0);
|
||||
m_legR.field_18 = true;
|
||||
m_legR.addBox(-2, 0, -2, 4, 12, 4, a);
|
||||
m_legR.setPos(2, b + 12, 0);
|
||||
}
|
||||
|
||||
void HumanoidModel::_logGraphics()
|
||||
{
|
||||
Matrix m;
|
||||
|
||||
if (Minecraft::customDebugId == 1)
|
||||
{
|
||||
// @NOTE: I think most of this function was ifdef'd/commented out
|
||||
m.fetchGL(GL_MODELVIEW_MATRIX);
|
||||
}
|
||||
}
|
||||
|
||||
void HumanoidModel::onGraphicsReset()
|
||||
{
|
||||
m_head.m_bCompiled = false;
|
||||
m_body.m_bCompiled = false;
|
||||
m_armL.m_bCompiled = false;
|
||||
m_armR.m_bCompiled = false;
|
||||
m_legL.m_bCompiled = false;
|
||||
m_legR.m_bCompiled = false;
|
||||
}
|
||||
|
||||
void HumanoidModel::render(float a, float b, float c, float d, float e, float f)
|
||||
{
|
||||
setupAnim(a, b, c, d, e, f);
|
||||
m_head.render(f);
|
||||
m_body.render(f);
|
||||
m_armL.render(f);
|
||||
m_armR.render(f);
|
||||
m_legL.render(f);
|
||||
m_legR.render(f);
|
||||
_logGraphics();
|
||||
}
|
||||
|
||||
void HumanoidModel::renderHorrible(float a, float b, float c, float d, float e, float f)
|
||||
{
|
||||
setupAnim(a, b, c, d, e, f);
|
||||
m_head.renderHorrible(f);
|
||||
m_body.renderHorrible(f);
|
||||
m_armL.renderHorrible(f);
|
||||
m_armR.renderHorrible(f);
|
||||
m_legL.renderHorrible(f);
|
||||
m_legR.renderHorrible(f);
|
||||
_logGraphics();
|
||||
}
|
||||
|
||||
void HumanoidModel::setupAnim(float a2, float a3, float a4, float a5, float a6, float a7)
|
||||
{
|
||||
//a6 = pitch, a5 = yaw-ish
|
||||
m_head.field_10 = a5 * 0.017453f;
|
||||
m_head.field_C = a6 * 0.017453f;
|
||||
if (m_head.field_C < -1.0f)
|
||||
m_head.field_C = -1.0f;
|
||||
if (m_head.field_C > 1.0f)
|
||||
m_head.field_C = 1.0f;
|
||||
float v12 = (a2 * 0.6662f) + 3.1416f;
|
||||
m_armL.field_C = (Mth::cos(v12) * 2.0f * a3) * 0.5f;
|
||||
m_armR.field_C = Mth::cos(a2 * 0.6662f) * 2.0f * a3 * 0.5f; // @HUH: multiplying by 2 and also by 1/2
|
||||
m_armL.field_14 = 0.0f;
|
||||
m_armR.field_14 = 0.0f;
|
||||
m_legL.field_C = (Mth::cos(a2 * 0.6662f) * 1.4f) * a3;
|
||||
m_legR.field_C = (Mth::cos(v12) * 1.4f) * a3;
|
||||
m_legL.field_10 = 0.0f;
|
||||
m_legR.field_10 = 0.0f;
|
||||
|
||||
if (field_8)
|
||||
{
|
||||
float v15 = (3.1416f * -0.5f) * 0.4f;
|
||||
m_armL.field_C += v15;
|
||||
m_armR.field_C += v15;
|
||||
float v16 = (3.1416f * -0.5f) * 0.8f;
|
||||
m_legL.field_C = v16;
|
||||
m_legR.field_C = v16;
|
||||
m_legL.field_10 = (3.1416f * 0.5f) * 0.2f;
|
||||
m_legR.field_10 = (3.1416f * -0.5f) * 0.2f;
|
||||
}
|
||||
|
||||
if (field_10BC)
|
||||
m_armR.field_C = ((3.1416f * 0.5f) * -0.2f) + (m_armR.field_C * 0.5f);
|
||||
if (field_10BD)
|
||||
m_armL.field_C = ((3.1416f * 0.5f) * -0.2f) + (m_armL.field_C * 0.5f);
|
||||
|
||||
m_armL.field_10 = 0.0f;
|
||||
m_armR.field_10 = 0.0f;
|
||||
|
||||
if (field_4 > -9990.0f)
|
||||
{
|
||||
m_body.field_10 = Mth::sin(Mth::sqrt(field_4) * 3.1416f * 2.0f) * 0.2f;
|
||||
m_armL.m_posZ = 5.0f * Mth::sin(m_body.field_10);
|
||||
m_armL.m_posX = -5.0f * Mth::cos(m_body.field_10);
|
||||
m_armR.m_posZ = -5.0f * Mth::sin(m_body.field_10);
|
||||
m_armR.m_posX = 5.0f * Mth::cos(m_body.field_10);
|
||||
m_armL.field_10 = m_armL.field_10 + m_body.field_10;
|
||||
m_armR.field_10 = m_armR.field_10 + m_body.field_10;
|
||||
float o = 1.0f - field_4;
|
||||
m_armR.field_C += m_body.field_10;
|
||||
m_armL.field_C -= -((m_head.field_C - 0.7f) * Mth::sin(3.1416f * field_4)) * 0.75f + Mth::sin((1.0f - o * o * o * o) * 3.1416f) * 1.2f;
|
||||
m_armL.field_10 += m_body.field_10 * 2.0f;
|
||||
m_armL.field_14 = Mth::sin(field_4 * 3.1416f) * -0.4f;
|
||||
}
|
||||
|
||||
if (field_10BE) // sneaking?
|
||||
{
|
||||
m_body.field_C = 0.5f;
|
||||
m_armL.field_C += 0.4f;
|
||||
m_armR.field_C += 0.4f;
|
||||
m_legL.m_posZ = 4.0f;
|
||||
m_legR.m_posZ = 4.0f;
|
||||
m_legL.m_posY = 9.0f;
|
||||
m_legR.m_posY = 9.0f;
|
||||
m_head.m_posY = 1.0f;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_body.field_C = 0.0f;
|
||||
m_legL.m_posZ = 0.0f;
|
||||
m_head.m_posY = 0.0f;
|
||||
m_legR.m_posZ = 0.0f;
|
||||
m_legL.m_posY = 12.0f;
|
||||
m_legR.m_posY = 12.0f;
|
||||
}
|
||||
|
||||
m_armL.field_14 += Mth::cos(a4 * 0.09f) * 0.05f + 0.05f;
|
||||
m_armR.field_14 -= Mth::cos(a4 * 0.09f) * 0.05f + 0.05f;
|
||||
m_armL.field_C += Mth::sin(a4 * 0.067f) * 0.05f;
|
||||
m_armR.field_C += Mth::sin(a4 * 0.067f) * -0.05f;
|
||||
}
|
||||
|
||||
/* Keeping the original around just in case:
|
||||
|
||||
void HumanoidModel::setupAnim(float a2, float a3, float a4, float a5, float a6, float a7)
|
||||
{
|
||||
this->m_head.field_10 = a5 * 0.017453f;
|
||||
float v11 = a6 * 0.017453f;
|
||||
if ((a6 * 0.017453f) <= 1.0f)
|
||||
{
|
||||
if (v11 < -1.0f)
|
||||
v11 = -1.0f;
|
||||
}
|
||||
else
|
||||
{
|
||||
v11 = 1.0f;
|
||||
}
|
||||
this->m_head.field_C = v11;
|
||||
float v12 = (a2 * 0.6662f) + 3.1416f;
|
||||
float v13 = Mth::cos(v12);
|
||||
this->m_armL.field_C = ((v13 + v13) * a3) * 0.5f;
|
||||
float v14 = Mth::cos(a2 * 0.6662f);
|
||||
this->m_armR.field_C = ((v14 + v14) * a3) * 0.5f;
|
||||
this->m_armL.field_14 = 0.0f;
|
||||
this->m_armR.field_14 = 0.0f;
|
||||
this->m_legL.field_C = (Mth::cos(a2 * 0.6662f) * 1.4f) * a3;
|
||||
this->m_legR.field_C = (Mth::cos(v12) * 1.4f) * a3;
|
||||
this->m_legL.field_10 = 0.0f;
|
||||
this->m_legR.field_10 = 0.0f;
|
||||
if (this->field_8)
|
||||
{
|
||||
float v15 = (3.1416f * -0.5f) * 0.4f;
|
||||
this->m_armL.field_C = this->m_armL.field_C + v15;
|
||||
this->m_armR.field_C = this->m_armR.field_C + v15;
|
||||
float v16 = (3.1416f * -0.5f) * 0.8f;
|
||||
this->m_legL.field_C = v16;
|
||||
this->m_legR.field_C = v16;
|
||||
this->m_legL.field_10 = (3.1416f * 0.5f) * 0.2f;
|
||||
this->m_legR.field_10 = (3.1416f * -0.5f) * 0.2f;
|
||||
}
|
||||
if (this->field_10BC)
|
||||
this->m_armR.field_C = ((3.1416f * 0.5f) * -0.2f) + (this->m_armR.field_C * 0.5f);
|
||||
if (this->field_10BD)
|
||||
this->m_armL.field_C = ((3.1416f * 0.5f) * -0.2f) + (this->m_armL.field_C * 0.5f);
|
||||
|
||||
this->m_armL.field_10 = 0.0f;
|
||||
this->m_armR.field_10 = 0.0f;
|
||||
if (field_4 > -9990.0f)
|
||||
{
|
||||
float v22 = Mth::sqrt(field_4);
|
||||
float v23 = Mth::sin((v22 * 3.1416f) + (v22 * 3.1416f));
|
||||
this->m_body.field_10 = v23 * 0.2f;
|
||||
float v24 = Mth::sin(v23 * 0.2f) * 5.0f;
|
||||
float bf10_1 = this->m_body.field_10;
|
||||
this->m_armL.m_posZ = v24;
|
||||
float v26 = Mth::cos(bf10_1) * -5.0f;
|
||||
float bf10_2 = this->m_body.field_10;
|
||||
this->m_armL.m_posX = v26;
|
||||
float v28 = Mth::sin(bf10_2) * -5.0f;
|
||||
float bf10_3 = this->m_body.field_10;
|
||||
this->m_armR.m_posZ = v28;
|
||||
this->m_armR.m_posX = Mth::cos(bf10_3) * 5.0f;
|
||||
float bf10_4 = this->m_body.field_10;
|
||||
this->m_armL.field_10 = this->m_armL.field_10 + bf10_4;
|
||||
this->m_armR.field_10 = this->m_armR.field_10 + bf10_4;
|
||||
float v31 = this->m_armR.field_C + bf10_4;
|
||||
float v32 = 1.0f - this->field_4;
|
||||
this->m_armR.field_C = v31;
|
||||
float v33 = Mth::sin((1.0f - ((v32 * v32) * (v32 * v32))) * 3.1416f);
|
||||
float v34 = Mth::sin(3.1416f * this->field_4);
|
||||
float bf10_times_2 = this->m_body.field_10 + this->m_body.field_10;
|
||||
this->m_armL.field_C = this->m_armL.field_C - ((-((this->m_head.field_C - 0.7f) * v34) * 0.75f) + (v33 * 1.2f));
|
||||
float v36 = this->m_armL.field_10 + bf10_times_2;
|
||||
float v37 = this->field_4 * 3.1416f;
|
||||
this->m_armL.field_10 = v36;
|
||||
this->m_armL.field_14 = Mth::sin(v37) * -0.4f;
|
||||
}
|
||||
if (this->field_10BE)
|
||||
{
|
||||
m_body.field_C = 0.5f;
|
||||
m_armL.field_C += 0.4f;
|
||||
m_armR.field_C += 0.4f;
|
||||
m_legL.m_posZ = 4.0f;
|
||||
m_legR.m_posZ = 4.0f;
|
||||
m_legL.m_posY = 9.0f;
|
||||
m_legR.m_posY = 9.0f;
|
||||
m_head.m_posY = 1.0f;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_body.field_C = 0.0f;
|
||||
m_legL.m_posZ = 0.0f;
|
||||
m_head.m_posY = 0.0f;
|
||||
m_legR.m_posZ = 0.0f;
|
||||
m_legL.m_posY = 12.0f;
|
||||
m_legR.m_posY = 12.0f;
|
||||
}
|
||||
|
||||
float v18 = this->m_armL.field_14;
|
||||
this->m_armL.field_14 = v18 + ((Mth::cos(a4 * 0.09f) * 0.05f) + 0.05f);
|
||||
float v19 = this->m_armR.field_14;
|
||||
this->m_armR.field_14 = v19 - ((Mth::cos(a4 * 0.09f) * 0.05f) + 0.05f);
|
||||
float v20 = this->m_armL.field_C;
|
||||
this->m_armL.field_C = v20 + (Mth::sin(a4 * 0.067f) * 0.05f);
|
||||
float v21 = this->m_armR.field_C;
|
||||
this->m_armR.field_C = v21 + (Mth::sin(a4 * 0.067f) * -0.05f);
|
||||
}
|
||||
*/
|
||||
24
source/World/Entity/Models/HumanoidModel.hpp
Normal file
24
source/World/Entity/Models/HumanoidModel.hpp
Normal file
@@ -0,0 +1,24 @@
|
||||
#pragma once
|
||||
|
||||
#include "Model.hpp"
|
||||
|
||||
class HumanoidModel : public Model
|
||||
{
|
||||
public:
|
||||
HumanoidModel(float a, float b);
|
||||
void _logGraphics();
|
||||
// @TODO - No xrefs: void render(HumanoidModel* a, float f);
|
||||
|
||||
void onGraphicsReset() override;
|
||||
void render(float, float, float, float, float, float) override;
|
||||
void renderHorrible(float, float, float, float, float, float) override;
|
||||
void setupAnim(float, float, float, float, float, float) override;
|
||||
|
||||
public:
|
||||
// @TODO: swap armL and armR.. Steve punches with the right hand.
|
||||
Cube m_head, m_body, m_armL, m_armR, m_legL, m_legR;
|
||||
bool field_10BC = false;
|
||||
bool field_10BD = false;
|
||||
bool field_10BE = false;
|
||||
};
|
||||
|
||||
26
source/World/Entity/Models/Model.cpp
Normal file
26
source/World/Entity/Models/Model.cpp
Normal file
@@ -0,0 +1,26 @@
|
||||
#include "Model.hpp"
|
||||
|
||||
void Model::onGraphicsReset()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void Model::prepareMobModel(Mob*, float, float, float)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void Model::render(float, float, float, float, float, float)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void Model::renderHorrible(float, float, float, float, float, float)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void Model::setupAnim(float, float, float, float, float, float)
|
||||
{
|
||||
|
||||
}
|
||||
18
source/World/Entity/Models/Model.hpp
Normal file
18
source/World/Entity/Models/Model.hpp
Normal file
@@ -0,0 +1,18 @@
|
||||
#pragma once
|
||||
|
||||
#include "Cube.hpp"
|
||||
#include "Mob.hpp"
|
||||
|
||||
class Model
|
||||
{
|
||||
public:
|
||||
virtual void onGraphicsReset();
|
||||
virtual void prepareMobModel(Mob*, float, float, float);
|
||||
virtual void render(float, float, float, float, float, float);
|
||||
virtual void renderHorrible(float, float, float, float, float, float);
|
||||
virtual void setupAnim(float, float, float, float, float, float);
|
||||
|
||||
public:
|
||||
float field_4 = 0.0f;
|
||||
bool field_8 = false;
|
||||
};
|
||||
299
source/World/Entity/Player.cpp
Normal file
299
source/World/Entity/Player.cpp
Normal file
@@ -0,0 +1,299 @@
|
||||
#include "Player.hpp"
|
||||
#include "Level.hpp"
|
||||
|
||||
Player::Player(Level* pLevel) : Mob(pLevel)
|
||||
{
|
||||
field_C8 = 2;
|
||||
|
||||
m_pInventory = new Inventory(this);
|
||||
|
||||
field_84 = 1.62f;
|
||||
|
||||
Pos pos = m_pLevel->getSharedSpawnPos();
|
||||
|
||||
moveTo(float(pos.x) + 0.5f, float(pos.y) + 1.0f, float(pos.z) + 0.5f, 0.0f, 0.0f);
|
||||
|
||||
m_health = 20;
|
||||
|
||||
m_class = "humanoid";
|
||||
m_texture = "mob/char.png";
|
||||
|
||||
field_C4 = 20;
|
||||
field_B5C = 180.0f;
|
||||
}
|
||||
|
||||
Player::~Player()
|
||||
{
|
||||
delete m_pInventory;
|
||||
}
|
||||
|
||||
void Player::remove()
|
||||
{
|
||||
Entity::remove();
|
||||
}
|
||||
|
||||
void Player::tick()
|
||||
{
|
||||
Mob::tick();
|
||||
}
|
||||
|
||||
bool Player::isInWall()
|
||||
{
|
||||
return Entity::isInWall();
|
||||
}
|
||||
|
||||
float Player::getHeadHeight()
|
||||
{
|
||||
return 0.12f; //@HUH: what?
|
||||
}
|
||||
|
||||
bool Player::isShootable()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Player::isPlayer()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Player::isCreativeModeAllowed()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Player::hurt(Entity* pEnt, int damage)
|
||||
{
|
||||
//@HUH
|
||||
return false;
|
||||
}
|
||||
|
||||
void Player::awardKillScore(Entity* pKilled, int score)
|
||||
{
|
||||
m_score += score;
|
||||
}
|
||||
|
||||
void Player::resetPos()
|
||||
{
|
||||
field_84 = 1.62f;
|
||||
setSize(0.6f, 1.8f);
|
||||
|
||||
Entity::resetPos();
|
||||
|
||||
m_health = 20;
|
||||
field_110 = 0;
|
||||
}
|
||||
|
||||
void Player::die(Entity* pCulprit)
|
||||
{
|
||||
Mob::die(pCulprit);
|
||||
setSize(0.2f, 0.2f);
|
||||
setPos(m_pos.x, m_pos.y, m_pos.z); // update hitbox
|
||||
m_vel.y = 0.1f;
|
||||
|
||||
if (pCulprit)
|
||||
{
|
||||
m_vel.x = -0.1f * Mth::cos(float((field_10C + m_yaw) * M_PI / 180.0));
|
||||
m_vel.z = -0.1f * Mth::cos(float((field_10C + m_yaw) * M_PI / 180.0));
|
||||
}
|
||||
else
|
||||
{
|
||||
m_vel.x = 0;
|
||||
m_vel.z = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void Player::aiStep()
|
||||
{
|
||||
field_B9C = field_BA0;
|
||||
float velLen = Mth::sqrt(m_vel.x * m_vel.x + m_vel.z * m_vel.z);
|
||||
float velYAtan = Mth::atan(m_vel.y * -0.2f), x1 = 0.0f;
|
||||
|
||||
if (velLen > 0.1f)
|
||||
velLen = 0.1f;
|
||||
|
||||
if (!field_7C)
|
||||
{
|
||||
if (m_health > 0)
|
||||
{
|
||||
velLen = 0;
|
||||
x1 = velYAtan * 15.0f;
|
||||
}
|
||||
else
|
||||
{
|
||||
velLen = x1 = 0.0f;
|
||||
}
|
||||
}
|
||||
|
||||
if (m_health <= 0)
|
||||
velLen = 0.0f;
|
||||
|
||||
field_BA0 += (velLen - field_BA0) * 0.4f;
|
||||
field_11C += (x1 - field_11C) * 0.8f;
|
||||
|
||||
if (m_health <= 0)
|
||||
return;
|
||||
|
||||
AABB scanAABB = m_hitbox;
|
||||
scanAABB.grow(1, 1, 1);
|
||||
|
||||
auto pEnts = m_pLevel->getEntities(this, scanAABB);
|
||||
|
||||
for (auto pEnt : *pEnts)
|
||||
{
|
||||
if (pEnt->m_bRemoved)
|
||||
continue;
|
||||
|
||||
touch(pEnt);
|
||||
}
|
||||
}
|
||||
|
||||
bool Player::isImmobile()
|
||||
{
|
||||
return m_health <= 0;
|
||||
}
|
||||
|
||||
void Player::updateAi()
|
||||
{
|
||||
if (field_BA4)
|
||||
{
|
||||
field_BA8++;
|
||||
if (field_BA8 > 7)
|
||||
{
|
||||
field_BA8 = 0;
|
||||
field_BA4 = false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
field_BA8 = 0;
|
||||
}
|
||||
|
||||
field_F8 = field_BA8 * 0.125f;
|
||||
}
|
||||
|
||||
void Player::defineSynchedData()
|
||||
{
|
||||
Mob::defineSynchedData();
|
||||
}
|
||||
|
||||
void Player::animateRespawn()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
int Player::addResource(int x)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
void Player::animateRespawn(Player*, Level*)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void Player::attack(Entity* pEnt)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
bool Player::canDestroy(Tile* pTile)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
void Player::closeContainer()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void Player::displayClientMessage(const std::string& msg)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void Player::drop()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
float Player::getDestroySpeed()
|
||||
{
|
||||
return 0.5f;
|
||||
}
|
||||
|
||||
int Player::getInventorySlot(int x)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
Pos Player::getRespawnPosition()
|
||||
{
|
||||
return m_respawnPos;
|
||||
}
|
||||
|
||||
int Player::getScore()
|
||||
{
|
||||
return m_score;
|
||||
}
|
||||
|
||||
void Player::prepareCustomTextures()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void Player::respawn()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void Player::rideTick()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void Player::setDefaultHeadHeight()
|
||||
{
|
||||
field_84 = 1.62f;
|
||||
}
|
||||
|
||||
void Player::setRespawnPos(Pos* pos)
|
||||
{
|
||||
if (!pos)
|
||||
{
|
||||
m_bHaveRespawnPos = false;
|
||||
return;
|
||||
}
|
||||
|
||||
m_bHaveRespawnPos = true;
|
||||
m_respawnPos.x = pos->x;
|
||||
m_respawnPos.y = pos->y;
|
||||
// @BUG: no m_respawnPos.z = pos->z ??
|
||||
}
|
||||
|
||||
void Player::startCrafting(int x, int y, int z)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void Player::swing()
|
||||
{
|
||||
LogMsg("Swing!");
|
||||
field_BA8 = -1;
|
||||
field_BA4 = true;
|
||||
}
|
||||
|
||||
void Player::take(Entity* pEnt, int x)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void Player::touch(Entity* pEnt)
|
||||
{
|
||||
pEnt->playerTouch(this);
|
||||
}
|
||||
|
||||
void Player::interact(Entity* pEnt)
|
||||
{
|
||||
pEnt->interact(this);
|
||||
}
|
||||
76
source/World/Entity/Player.hpp
Normal file
76
source/World/Entity/Player.hpp
Normal file
@@ -0,0 +1,76 @@
|
||||
#pragma once
|
||||
|
||||
#include "Mob.hpp"
|
||||
#include "Inventory.hpp"
|
||||
#include "RakNetTypes.h"
|
||||
|
||||
class Inventory; // in case we're included from Inventory.hpp
|
||||
|
||||
class Player : public Mob
|
||||
{
|
||||
public:
|
||||
Player(Level*);
|
||||
virtual ~Player();
|
||||
|
||||
virtual void remove() override;
|
||||
virtual void tick() override;
|
||||
virtual bool isInWall() override;
|
||||
virtual float getHeadHeight() override;
|
||||
virtual bool isShootable() override;
|
||||
virtual bool isPlayer() override;
|
||||
virtual bool isCreativeModeAllowed() override;
|
||||
virtual bool hurt(Entity*, int) override;
|
||||
virtual void awardKillScore(Entity* pKilled, int score) override;
|
||||
virtual void resetPos() override;
|
||||
virtual void die(Entity* pCulprit) override;
|
||||
virtual void aiStep() override;
|
||||
virtual bool isImmobile() override;
|
||||
virtual void updateAi() override;
|
||||
virtual void defineSynchedData() override;
|
||||
|
||||
virtual void animateRespawn();
|
||||
|
||||
int addResource(int);
|
||||
void animateRespawn(Player*, Level*);
|
||||
void attack(Entity* pEnt);
|
||||
bool canDestroy(Tile*);
|
||||
void closeContainer();
|
||||
void displayClientMessage(const std::string& msg);
|
||||
// TODO: void drop(ItemInstance*);
|
||||
// TODO: void drop(ItemInstance*, bool);
|
||||
void drop();
|
||||
float getDestroySpeed();
|
||||
int getInventorySlot(int x);
|
||||
Pos getRespawnPosition();
|
||||
int getScore();
|
||||
void prepareCustomTextures();
|
||||
// TODO: void reallyDrop(ItemEntity* pEnt);
|
||||
void respawn();
|
||||
void rideTick();
|
||||
void setDefaultHeadHeight();
|
||||
void setRespawnPos(Pos*);
|
||||
void startCrafting(int, int, int);
|
||||
void swing();
|
||||
void take(Entity* pEnt, int x);
|
||||
void touch(Entity* pEnt);
|
||||
void interact(Entity* pEnt);
|
||||
|
||||
public:
|
||||
//TODO
|
||||
Inventory* m_pInventory = nullptr;
|
||||
uint8_t field_B94 = 0;
|
||||
int m_score = 0;
|
||||
float field_B9C = 0.0f;
|
||||
float field_BA0 = 0.0f;
|
||||
bool field_BA4 = false;
|
||||
int field_BA8 = 0;
|
||||
std::string m_name = "";
|
||||
int field_BC4 = 0;
|
||||
RakNet::RakNetGUID m_guid;
|
||||
//TODO
|
||||
Pos m_respawnPos;
|
||||
//TODO
|
||||
bool m_bHaveRespawnPos = false;
|
||||
//TODO
|
||||
};
|
||||
|
||||
69
source/World/Entity/PrimedTnt.cpp
Normal file
69
source/World/Entity/PrimedTnt.cpp
Normal file
@@ -0,0 +1,69 @@
|
||||
#include "PrimedTnt.hpp"
|
||||
#include "Level.hpp"
|
||||
|
||||
PrimedTnt::PrimedTnt(Level* level) : Entity(level)
|
||||
{
|
||||
m_fuseTimer = 0;
|
||||
field_C8 = RENDER_TNT;
|
||||
field_34 = 1;
|
||||
setSize(0.98f, 0.98f);
|
||||
field_84 = field_8C * 0.5f;
|
||||
}
|
||||
|
||||
PrimedTnt::PrimedTnt(Level* level, float x, float y, float z) : PrimedTnt(level)
|
||||
{
|
||||
setPos(x, y, z);
|
||||
|
||||
float fAng = 0.017453f * 2.0f * float(M_PI) * Mth::random();
|
||||
|
||||
m_vel.x = -0.02f * Mth::sin(fAng);
|
||||
m_vel.z = -0.02f * Mth::cos(fAng);
|
||||
m_vel.y = 0.2f;
|
||||
|
||||
field_3C = m_pos;
|
||||
|
||||
m_fuseTimer = 80; // 4 secs
|
||||
}
|
||||
|
||||
void PrimedTnt::explode()
|
||||
{
|
||||
// @NOTE: Not passing `this` as pointer to entity
|
||||
m_pLevel->explode(nullptr, m_pos.x, m_pos.y, m_pos.z, 2.5f);
|
||||
}
|
||||
|
||||
float PrimedTnt::getShadowHeightOffs()
|
||||
{
|
||||
return 0.0f;
|
||||
}
|
||||
|
||||
bool PrimedTnt::isPickable()
|
||||
{
|
||||
return !m_bRemoved;
|
||||
}
|
||||
|
||||
void PrimedTnt::tick()
|
||||
{
|
||||
field_3C = m_pos;
|
||||
|
||||
m_vel.y -= 0.04f;
|
||||
move(m_vel.x, m_vel.y, m_vel.z);
|
||||
|
||||
m_vel *= 0.98f;
|
||||
if (field_7C)
|
||||
{
|
||||
m_vel.x *= 0.7f;
|
||||
m_vel.z *= 0.7f;
|
||||
m_vel.y *= -0.5f;
|
||||
}
|
||||
|
||||
m_fuseTimer--;
|
||||
if (m_fuseTimer <= 0)
|
||||
{
|
||||
remove();
|
||||
explode();
|
||||
}
|
||||
else
|
||||
{
|
||||
m_pLevel->addParticle("smoke", m_pos.x, m_pos.y + 0.5f, m_pos.z, 0.0f, 0.0f, 0.0f);
|
||||
}
|
||||
}
|
||||
20
source/World/Entity/PrimedTnt.hpp
Normal file
20
source/World/Entity/PrimedTnt.hpp
Normal file
@@ -0,0 +1,20 @@
|
||||
#pragma once
|
||||
|
||||
#include "Entity.hpp"
|
||||
|
||||
class PrimedTnt : public Entity
|
||||
{
|
||||
public:
|
||||
PrimedTnt(Level*);
|
||||
PrimedTnt(Level*, float, float, float);
|
||||
|
||||
float getShadowHeightOffs() override;
|
||||
bool isPickable() override;
|
||||
void tick() override;
|
||||
|
||||
void explode();
|
||||
|
||||
public:
|
||||
int m_fuseTimer;
|
||||
};
|
||||
|
||||
94
source/World/Entity/TripodCamera.cpp
Normal file
94
source/World/Entity/TripodCamera.cpp
Normal file
@@ -0,0 +1,94 @@
|
||||
#include "TripodCamera.hpp"
|
||||
#include "Player.hpp"
|
||||
#include "Level.hpp"
|
||||
|
||||
TripodCamera::TripodCamera(Level* level, Player* player, float x, float y, float z) : Mob(level)
|
||||
{
|
||||
m_owner = player;
|
||||
field_C8 = RENDER_CAMERA;
|
||||
|
||||
field_60 = m_pitch = player->m_pitch;
|
||||
field_5C = m_yaw = player->m_yaw;
|
||||
|
||||
field_34 = 1;
|
||||
|
||||
setSize(1.0f, 1.5f);
|
||||
field_84 = field_8C * 0.5f - 0.25f;
|
||||
|
||||
setPos(x, y, z);
|
||||
field_3C.x = x;
|
||||
field_3C.y = y;
|
||||
field_3C.z = z;
|
||||
}
|
||||
|
||||
void TripodCamera::defineSynchedData()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
float TripodCamera::getShadowHeightOffs()
|
||||
{
|
||||
return 0.0f;
|
||||
}
|
||||
|
||||
bool TripodCamera::interact(Player* player)
|
||||
{
|
||||
// @BUG-ish: No check for owner?
|
||||
m_bActive = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
int TripodCamera::interactPreventDefault()
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
bool TripodCamera::isPickable()
|
||||
{
|
||||
return !m_bRemoved;
|
||||
}
|
||||
|
||||
bool TripodCamera::isPushable()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
void TripodCamera::tick()
|
||||
{
|
||||
field_3C = m_pos;
|
||||
|
||||
m_vel.y -= 0.04f;
|
||||
move(m_vel.x, m_vel.y, m_vel.z);
|
||||
|
||||
m_vel *= 0.98f;
|
||||
if (field_7C)
|
||||
{
|
||||
m_vel.x *= 0.7f;
|
||||
m_vel.z *= 0.7f;
|
||||
m_vel.y *= -0.5f;
|
||||
}
|
||||
|
||||
if (!m_bActive)
|
||||
return;
|
||||
|
||||
field_B90--;
|
||||
if (field_B90 == 0)
|
||||
{
|
||||
remove();
|
||||
return;
|
||||
}
|
||||
|
||||
if (field_B90 == 8)
|
||||
{
|
||||
m_pLevel->takePicture(this, m_owner);
|
||||
m_pLevel->addParticle("explode", m_pos.x, m_pos.y + 0.6f, m_pos.z, 0.0f, 0.0f, 0.0f);
|
||||
m_pLevel->addParticle("explode", m_pos.x, m_pos.y + 0.8f, m_pos.z, 0.0f, 0.0f, 0.0f);
|
||||
m_pLevel->addParticle("explode", m_pos.x, m_pos.y + 1.0f, m_pos.z, 0.0f, 0.0f, 0.0f);
|
||||
return;
|
||||
}
|
||||
|
||||
if (field_B90 > 8)
|
||||
{
|
||||
m_pLevel->addParticle("smoke", m_pos.x, m_pos.y + 1.0f, m_pos.z, 0.0f, 0.0f, 0.0f);
|
||||
}
|
||||
}
|
||||
27
source/World/Entity/TripodCamera.hpp
Normal file
27
source/World/Entity/TripodCamera.hpp
Normal file
@@ -0,0 +1,27 @@
|
||||
#pragma once
|
||||
|
||||
#include "Mob.hpp"
|
||||
|
||||
class Level;
|
||||
class Player;
|
||||
|
||||
class TripodCamera : public Mob
|
||||
{
|
||||
public:
|
||||
TripodCamera(Level*, Player*, float, float, float);
|
||||
|
||||
void defineSynchedData() override;
|
||||
float getShadowHeightOffs() override;
|
||||
bool interact(Player* player) override;
|
||||
int interactPreventDefault() override;
|
||||
bool isPickable() override;
|
||||
bool isPushable() override;
|
||||
void tick() override;
|
||||
|
||||
public:
|
||||
int field_B8C = 0;
|
||||
int field_B90 = 80;
|
||||
Player* m_owner = nullptr;
|
||||
bool m_bActive = false;
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user