forked from Kolyah35/minecraft-pe-0.6.1
the whole game
This commit is contained in:
346
src/world/entity/projectile/Arrow.cpp
Executable file
346
src/world/entity/projectile/Arrow.cpp
Executable file
@@ -0,0 +1,346 @@
|
||||
#include "Arrow.h"
|
||||
#include "../Mob.h"
|
||||
#include "../player/Player.h"
|
||||
#include "../../item/Item.h"
|
||||
#include "../../item/ItemInstance.h"
|
||||
#include "../../level/Level.h"
|
||||
#include "../../level/tile/Tile.h"
|
||||
#include "../../../util/Mth.h"
|
||||
|
||||
#include "../../../nbt/CompoundTag.h"
|
||||
|
||||
const float Arrow::ARROW_BASE_DAMAGE = 2.0f;
|
||||
|
||||
Arrow::Arrow( Level* level )
|
||||
: super(level),
|
||||
playerArrow(false),
|
||||
ownerId(0)
|
||||
{
|
||||
_init();
|
||||
}
|
||||
|
||||
Arrow::Arrow( Level* level, float x, float y, float z )
|
||||
: super(level),
|
||||
playerArrow(false),
|
||||
ownerId(0)
|
||||
{
|
||||
_init();
|
||||
|
||||
this->setPos(x, y, z);
|
||||
this->heightOffset = 0;
|
||||
}
|
||||
|
||||
Arrow::Arrow( Level* level, Mob* mob, float power )
|
||||
: super(level),
|
||||
ownerId(mob->entityId),
|
||||
playerArrow(mob->isPlayer())
|
||||
{
|
||||
_init();
|
||||
|
||||
moveTo(mob->x, mob->y + mob->getHeadHeight(), mob->z, mob->yRot, mob->xRot);
|
||||
|
||||
const float dx = Mth::cos(yRot * Mth::DEGRAD);
|
||||
const float dz = Mth::sin(yRot * Mth::DEGRAD);
|
||||
x -= dx * 0.16f;
|
||||
y -= 0.1f;
|
||||
z -= dz * 0.16f;
|
||||
this->setPos(x, y, z);
|
||||
this->heightOffset = 0;
|
||||
|
||||
const float dxx = Mth::cos(xRot / 180 * Mth::PI);
|
||||
xd = -dz * dxx;
|
||||
zd = dx * dxx;
|
||||
yd = -Mth::sin(xRot / 180 * Mth::PI);
|
||||
|
||||
shoot(xd, yd, zd, power * 1.5f, 1);
|
||||
}
|
||||
|
||||
void Arrow::_init()
|
||||
{
|
||||
entityRendererId = ER_ARROW_RENDERER;
|
||||
setSize(0.5f, 0.5f);
|
||||
|
||||
shakeTime = 0;
|
||||
critArrow = false;
|
||||
|
||||
xTile = -1;
|
||||
yTile = -1;
|
||||
zTile = -1;
|
||||
lastTile = 0;
|
||||
lastData = 0;
|
||||
inGround = false;
|
||||
life = 0;
|
||||
flightTime = 0;
|
||||
}
|
||||
|
||||
void Arrow::shoot( float xd, float yd, float zd, float pow, float uncertainty )
|
||||
{
|
||||
float dist = Mth::sqrt(xd * xd + yd * yd + zd * zd);
|
||||
|
||||
xd /= dist;
|
||||
yd /= dist;
|
||||
zd /= dist;
|
||||
|
||||
const float radius = 0.0075f * uncertainty;
|
||||
xd += sharedRandom.nextGaussian() * radius;
|
||||
yd += sharedRandom.nextGaussian() * radius;
|
||||
zd += sharedRandom.nextGaussian() * radius;
|
||||
|
||||
xd *= pow;
|
||||
yd *= pow;
|
||||
zd *= pow;
|
||||
|
||||
this->xd = xd;
|
||||
this->yd = yd;
|
||||
this->zd = zd;
|
||||
|
||||
float sd = (float) Mth::sqrt(xd * xd + zd * zd);
|
||||
|
||||
yRotO = this->yRot = (float) (std::atan2(xd, zd) * Mth::RADDEG);
|
||||
xRotO = this->xRot = (float) (std::atan2(yd, sd) * Mth::RADDEG);
|
||||
life = 0;
|
||||
}
|
||||
|
||||
void Arrow::lerpMotion( float xd, float yd, float zd )
|
||||
{
|
||||
this->xd = xd;
|
||||
this->yd = yd;
|
||||
this->zd = zd;
|
||||
if (xRotO == 0 && yRotO == 0) {
|
||||
float sd = (float) Mth::sqrt(xd * xd + zd * zd);
|
||||
yRotO = this->yRot = (float) (std::atan2(xd, zd) * Mth::RADDEG);
|
||||
xRotO = this->xRot = (float) (std::atan2(yd, sd) * Mth::RADDEG);
|
||||
moveTo(x, y, z, yRot, xRot);
|
||||
life = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void Arrow::tick()
|
||||
{
|
||||
super::tick();
|
||||
|
||||
if (xRotO == 0 && yRotO == 0) {
|
||||
float sd = (float) Mth::sqrt(xd * xd + zd * zd);
|
||||
yRotO = this->yRot = (float) (std::atan2(xd, zd) * Mth::RADDEG);
|
||||
xRotO = this->xRot = (float) (std::atan2(yd, sd) * Mth::RADDEG);
|
||||
}
|
||||
|
||||
|
||||
{
|
||||
int t = level->getTile(xTile, yTile, zTile);
|
||||
if (t > 0) {
|
||||
Tile::tiles[t]->updateShape(level, xTile, yTile, zTile);
|
||||
AABB* aabb = Tile::tiles[t]->getAABB(level, xTile, yTile, zTile);
|
||||
if (aabb != NULL && aabb->contains(Vec3(x, y, z))) {
|
||||
inGround = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (shakeTime > 0) shakeTime--;
|
||||
|
||||
if (inGround) {
|
||||
// xd = 0;
|
||||
// yd = 0;
|
||||
// zd = 0;
|
||||
int tile = level->getTile(xTile, yTile, zTile);
|
||||
int data = level->getData(xTile, yTile, zTile);
|
||||
if (tile != lastTile || data != lastData) {
|
||||
inGround = false;
|
||||
|
||||
xd *= sharedRandom.nextFloat() * 0.2f;
|
||||
yd *= sharedRandom.nextFloat() * 0.2f;
|
||||
zd *= sharedRandom.nextFloat() * 0.2f;
|
||||
life = 0;
|
||||
flightTime = 0;
|
||||
return;
|
||||
} else {
|
||||
if (++life == 60 * SharedConstants::TicksPerSecond) remove();
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
flightTime++;
|
||||
}
|
||||
|
||||
Vec3 from(x, y, z);
|
||||
Vec3 to(x + xd, y + yd, z + zd);
|
||||
HitResult res = level->clip(from, to, false, true);
|
||||
|
||||
from.set(x, y, z);
|
||||
to.set(x + xd, y + yd, z + zd);
|
||||
if (res.isHit()) {
|
||||
to.set(res.pos.x, res.pos.y, res.pos.z);
|
||||
}
|
||||
Entity* hitEntity = NULL;
|
||||
EntityList& objects = level->getEntities(this, this->bb.expand(xd, yd, zd).grow(1, 1, 1));
|
||||
float nearest = 0;
|
||||
for (unsigned int i = 0; i < objects.size(); i++) {
|
||||
Entity* e = objects[i];
|
||||
if (!e->isPickable() || (e->entityId == ownerId && flightTime < 5)) continue;
|
||||
|
||||
float rr = 0.3f;
|
||||
AABB bb = e->bb.grow(rr, rr, rr);
|
||||
HitResult p = bb.clip(from, to);
|
||||
if (p.isHit()) {
|
||||
float dd = from.distanceTo(p.pos);
|
||||
if (dd < nearest || nearest == 0) {
|
||||
hitEntity = e;
|
||||
nearest = dd;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (hitEntity != NULL) {
|
||||
res = HitResult(hitEntity);
|
||||
}
|
||||
|
||||
if (res.isHit()) {
|
||||
if (res.type == ENTITY) {
|
||||
float pow = Mth::sqrt(xd * xd + yd * yd + zd * zd);
|
||||
int dmg = (int) std::ceil(pow * ARROW_BASE_DAMAGE);
|
||||
|
||||
if (critArrow) dmg += sharedRandom.nextInt(dmg / 2 + 2);
|
||||
|
||||
//@todo
|
||||
//DamageSource damageSource = NULL;
|
||||
//if (owner == NULL) {
|
||||
// damageSource = DamageSource.arrow(this, this);
|
||||
//} else {
|
||||
// damageSource = DamageSource.arrow(this, owner);
|
||||
//}
|
||||
|
||||
//if (res.entity->hurt(damageSource, dmg)) {
|
||||
// if (res.entity instanceof Mob) {
|
||||
|
||||
if (res.entity->hurt(this, dmg)) {
|
||||
if (res.entity->isMob()) {
|
||||
((Mob*) res.entity)->arrowCount++;
|
||||
}
|
||||
level->playSound(this, "random.bowhit", 1.0f, 1.2f / (sharedRandom.nextFloat() * 0.2f + 0.9f));
|
||||
remove();
|
||||
} else {
|
||||
xd *= -0.1f;
|
||||
yd *= -0.1f;
|
||||
zd *= -0.1f;
|
||||
yRot += 180;
|
||||
yRotO += 180;
|
||||
flightTime = 0;
|
||||
}
|
||||
} else {
|
||||
xTile = res.x;
|
||||
yTile = res.y;
|
||||
zTile = res.z;
|
||||
lastTile = level->getTile(xTile, yTile, zTile);
|
||||
lastData = level->getData(xTile, yTile, zTile);
|
||||
xd = (float) (res.pos.x - x);
|
||||
yd = (float) (res.pos.y - y);
|
||||
zd = (float) (res.pos.z - z);
|
||||
float dd = Mth::sqrt(xd * xd + yd * yd + zd * zd);
|
||||
x -= (xd / dd) * 0.05f;
|
||||
y -= (yd / dd) * 0.05f;
|
||||
z -= (zd / dd) * 0.05f;
|
||||
|
||||
level->playSound(this, "random.bowhit", 1.0f, 1.2f / (sharedRandom.nextFloat() * 0.2f + 0.9f));
|
||||
inGround = true;
|
||||
shakeTime = 7;
|
||||
critArrow = false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (critArrow) {
|
||||
for (int i = 0; i < 4; i++) {
|
||||
level->addParticle(PARTICLETYPE(crit), x + xd * i / 4.0f, y + yd * i / 4.0f, z + zd * i / 4.0f, -xd, -yd + 0.2f, -zd);
|
||||
}
|
||||
}
|
||||
|
||||
x += xd;
|
||||
y += yd;
|
||||
z += zd;
|
||||
|
||||
float sd = Mth::sqrt(xd * xd + zd * zd);
|
||||
yRot = std::atan2(xd, zd) * Mth::RADDEG;
|
||||
xRot = std::atan2(yd, sd) * Mth::RADDEG;
|
||||
|
||||
while (xRot - xRotO < -180)
|
||||
xRotO -= 360;
|
||||
while (xRot - xRotO >= 180)
|
||||
xRotO += 360;
|
||||
|
||||
while (yRot - yRotO < -180)
|
||||
yRotO -= 360;
|
||||
while (yRot - yRotO >= 180)
|
||||
yRotO += 360;
|
||||
|
||||
xRot = xRotO + (xRot - xRotO) * 0.2f;
|
||||
yRot = yRotO + (yRot - yRotO) * 0.2f;
|
||||
|
||||
|
||||
float inertia = 0.99f;
|
||||
float gravity = 0.05f;
|
||||
|
||||
if (isInWater()) {
|
||||
for (int i = 0; i < 4; i++) {
|
||||
float s = 1 / 4.0f;
|
||||
level->addParticle(PARTICLETYPE(bubble), x - xd * s, y - yd * s, z - zd * s, xd, yd, zd);
|
||||
}
|
||||
inertia = 0.80f;
|
||||
}
|
||||
|
||||
xd *= inertia;
|
||||
yd *= inertia;
|
||||
zd *= inertia;
|
||||
yd -= gravity;
|
||||
|
||||
setPos(x, y, z);
|
||||
}
|
||||
|
||||
void Arrow::addAdditonalSaveData( CompoundTag* tag )
|
||||
{
|
||||
tag->putShort("xTile", (short) xTile);
|
||||
tag->putShort("yTile", (short) yTile);
|
||||
tag->putShort("zTile", (short) zTile);
|
||||
tag->putByte("inTile", (char) lastTile);
|
||||
tag->putByte("inData", (char) lastData);
|
||||
tag->putByte("shake", (char) shakeTime);
|
||||
tag->putByte("inGround", (char) (inGround ? 1 : 0));
|
||||
tag->putBoolean("player", playerArrow);
|
||||
}
|
||||
|
||||
void Arrow::readAdditionalSaveData( CompoundTag* tag )
|
||||
{
|
||||
xTile = tag->getShort("xTile");
|
||||
yTile = tag->getShort("yTile");
|
||||
zTile = tag->getShort("zTile");
|
||||
lastTile = tag->getByte("inTile") & 0xff;
|
||||
lastData = tag->getByte("inData") & 0xff;
|
||||
shakeTime = tag->getByte("shake") & 0xff;
|
||||
inGround = tag->getByte("inGround") == 1;
|
||||
playerArrow = tag->getBoolean("player");
|
||||
}
|
||||
|
||||
void Arrow::playerTouch( Player* player )
|
||||
{
|
||||
if (level->isClientSide) return;
|
||||
|
||||
if (inGround && playerArrow && shakeTime <= 0) {
|
||||
ItemInstance item(Item::arrow, 1);
|
||||
if (player->inventory->add(&item)) {
|
||||
level->playSound(this, "random.pop", 0.2f, ((sharedRandom.nextFloat() - sharedRandom.nextFloat()) * 0.7f + 1.0f) * 2.f);
|
||||
player->take(this, 1);
|
||||
remove();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
float Arrow::getShadowHeightOffs() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int Arrow::getEntityTypeId() const {
|
||||
return EntityTypes::IdArrow;
|
||||
}
|
||||
|
||||
int Arrow::getAuxData() {
|
||||
return ownerId;
|
||||
}
|
||||
57
src/world/entity/projectile/Arrow.h
Executable file
57
src/world/entity/projectile/Arrow.h
Executable file
@@ -0,0 +1,57 @@
|
||||
#ifndef NET_MINECRAFT_WORLD_ENTITY_PROJECTILE__Arrow_H__
|
||||
#define NET_MINECRAFT_WORLD_ENTITY_PROJECTILE__Arrow_H__
|
||||
|
||||
//package net.minecraft.world.entity.projectile;
|
||||
|
||||
#include "../Entity.h"
|
||||
|
||||
class Level;
|
||||
class Mob;
|
||||
class CompoundTag;
|
||||
|
||||
class Arrow: public Entity
|
||||
{
|
||||
typedef Entity super;
|
||||
// base damage, multiplied with velocity
|
||||
static const float ARROW_BASE_DAMAGE;
|
||||
|
||||
public:
|
||||
Arrow(Level* level);
|
||||
Arrow(Level* level, float x, float y, float z);
|
||||
Arrow(Level* level, Mob* mob, float power);
|
||||
|
||||
void _init();
|
||||
|
||||
void shoot(float xd, float yd, float zd, float pow, float uncertainty);
|
||||
|
||||
void lerpMotion(float xd, float yd, float zd);
|
||||
|
||||
void tick();
|
||||
|
||||
int getEntityTypeId() const;
|
||||
|
||||
void addAdditonalSaveData(CompoundTag* tag);
|
||||
void readAdditionalSaveData(CompoundTag* tag);
|
||||
|
||||
void playerTouch(Player* player);
|
||||
|
||||
float getShadowHeightOffs();
|
||||
|
||||
int getAuxData();
|
||||
public:
|
||||
bool playerArrow;
|
||||
int shakeTime;
|
||||
int ownerId;
|
||||
bool critArrow;
|
||||
private:
|
||||
int xTile;
|
||||
int yTile;
|
||||
int zTile;
|
||||
int lastTile;
|
||||
int lastData;
|
||||
bool inGround;
|
||||
int life;
|
||||
int flightTime;
|
||||
};
|
||||
|
||||
#endif /*NET_MINECRAFT_WORLD_ENTITY_PROJECTILE__Arrow_H__*/
|
||||
50
src/world/entity/projectile/Snowball.h
Executable file
50
src/world/entity/projectile/Snowball.h
Executable file
@@ -0,0 +1,50 @@
|
||||
#ifndef NET_MINECRAFT_WORLD_ENTITY_PROJECTILE__Snowball_H__
|
||||
#define NET_MINECRAFT_WORLD_ENTITY_PROJECTILE__Snowball_H__
|
||||
|
||||
//package net.minecraft.world.entity->projectile;
|
||||
|
||||
#include "Throwable.h"
|
||||
#include "../Mob.h"
|
||||
#include "../../level/Level.h"
|
||||
#include "../../phys/HitResult.h"
|
||||
|
||||
class Snowball: public Throwable
|
||||
{
|
||||
typedef Throwable super;
|
||||
public:
|
||||
Snowball(Level* level)
|
||||
: super(level)
|
||||
{
|
||||
entityRendererId = ER_SNOWBALL_RENDERER;
|
||||
}
|
||||
|
||||
Snowball(Level* level, Mob* mob)
|
||||
: super(level, mob)
|
||||
{
|
||||
entityRendererId = ER_SNOWBALL_RENDERER;
|
||||
}
|
||||
|
||||
Snowball(Level* level, float x, float y, float z)
|
||||
: super(level, x, y, z)
|
||||
{
|
||||
entityRendererId = ER_SNOWBALL_RENDERER;
|
||||
}
|
||||
|
||||
virtual int getEntityTypeId() const {
|
||||
return EntityTypes::IdSnowball;
|
||||
}
|
||||
|
||||
/*@Override*/
|
||||
void onHit(const HitResult& res) {
|
||||
if (res.type == ENTITY)
|
||||
res.entity->hurt(this, 0);
|
||||
|
||||
for (int i = 0; i < 6; i++)
|
||||
level->addParticle(PARTICLETYPE(snowballpoof), x, y, z, 0, 0, 0);
|
||||
|
||||
if (!level->isClientSide)
|
||||
remove();
|
||||
}
|
||||
};
|
||||
|
||||
#endif /*NET_MINECRAFT_WORLD_ENTITY_PROJECTILE__Snowball_H__*/
|
||||
260
src/world/entity/projectile/Throwable.cpp
Executable file
260
src/world/entity/projectile/Throwable.cpp
Executable file
@@ -0,0 +1,260 @@
|
||||
#include "Throwable.h"
|
||||
#include "../player/Player.h"
|
||||
#include "../../level/Level.h"
|
||||
#include "../../../util/Mth.h"
|
||||
#include "../../phys/HitResult.h"
|
||||
|
||||
Throwable::Throwable( Level* level )
|
||||
: super(level)
|
||||
{
|
||||
_init();
|
||||
setSize(0.25f, 0.25f);
|
||||
}
|
||||
|
||||
Throwable::Throwable( Level* level, Mob* mob )
|
||||
: super(level)
|
||||
{
|
||||
_init();
|
||||
setSize(0.25f, 0.25f);
|
||||
|
||||
ownerId = mob->entityId;
|
||||
|
||||
this->moveTo(mob->x, mob->y + mob->getHeadHeight(), mob->z, mob->yRot, mob->xRot);
|
||||
|
||||
const float rcos = Mth::cos(yRot / 180 * Mth::PI);
|
||||
const float rsin = Mth::sin(yRot / 180 * Mth::PI);
|
||||
x -= rcos * 0.16f;
|
||||
y -= 0.1f;
|
||||
z -= rsin * 0.16f;
|
||||
this->setPos(x, y, z);
|
||||
this->heightOffset = 0;
|
||||
|
||||
if (mob->isPlayer()) {
|
||||
shoot(mob->aimDirection, getThrowPower(), 1);
|
||||
} else {
|
||||
float xd = (-rsin * Mth::cos(xRot / 180 * Mth::PI));
|
||||
float zd = ( rcos * Mth::cos(xRot / 180 * Mth::PI));
|
||||
float yd = (-Mth::sin((xRot + getThrowUpAngleOffset()) / 180 * Mth::PI));
|
||||
shoot(xd, yd, zd, getThrowPower(), 1);
|
||||
}
|
||||
}
|
||||
|
||||
Throwable::Throwable( Level* level, float x, float y, float z )
|
||||
: super(level)
|
||||
{
|
||||
_init();
|
||||
setSize(0.25f, 0.25f);
|
||||
|
||||
this->setPos(x, y, z);
|
||||
this->heightOffset = 0;
|
||||
}
|
||||
|
||||
void Throwable::_init() {
|
||||
ownerId = 0;
|
||||
shakeTime = 0;
|
||||
inGround = false;
|
||||
|
||||
life = 0;
|
||||
flightTime = 0;
|
||||
xTile = -1;
|
||||
yTile = -1;
|
||||
zTile = -1;
|
||||
lastTile = 0;
|
||||
}
|
||||
|
||||
bool Throwable::shouldRenderAtSqrDistance( float distance ) {
|
||||
float size = bb.getSize() * 4;
|
||||
size *= 64.0f;
|
||||
return distance < size * size;
|
||||
}
|
||||
|
||||
float Throwable::getThrowPower() {
|
||||
return 1.5f;
|
||||
}
|
||||
|
||||
float Throwable::getThrowUpAngleOffset() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
float Throwable::getGravity() {
|
||||
return 0.03f;
|
||||
}
|
||||
|
||||
void Throwable::shoot(const Vec3& v, float pow, float uncertainty) {
|
||||
shoot(v.x, v.y, v.z, pow, uncertainty);
|
||||
}
|
||||
|
||||
void Throwable::shoot( float xd, float yd, float zd, float pow, float uncertainty ) {
|
||||
float dist = Mth::sqrt(xd * xd + yd * yd + zd * zd);
|
||||
|
||||
if (dist >= 0.001f) {
|
||||
xd /= dist;
|
||||
yd /= dist;
|
||||
zd /= dist;
|
||||
} else {
|
||||
xd = yd = zd = 0;
|
||||
}
|
||||
|
||||
xd += (sharedRandom.nextGaussian()) * 0.0075f * uncertainty;
|
||||
yd += (sharedRandom.nextGaussian()) * 0.0075f * uncertainty;
|
||||
zd += (sharedRandom.nextGaussian()) * 0.0075f * uncertainty;
|
||||
|
||||
xd *= pow;
|
||||
yd *= pow;
|
||||
zd *= pow;
|
||||
|
||||
this->xd = xd;
|
||||
this->yd = yd;
|
||||
this->zd = zd;
|
||||
|
||||
float sd = (float) Mth::sqrt(xd * xd + zd * zd);
|
||||
|
||||
yRotO = this->yRot = (float) (Mth::atan2(xd, zd) * 180 / Mth::PI);
|
||||
xRotO = this->xRot = (float) (Mth::atan2(yd, sd) * 180 / Mth::PI);
|
||||
life = 0;
|
||||
}
|
||||
|
||||
void Throwable::lerpMotion( float xd, float yd, float zd ) {
|
||||
this->xd = xd;
|
||||
this->yd = yd;
|
||||
this->zd = zd;
|
||||
if (xRotO == 0 && yRotO == 0) {
|
||||
float sd = (float) Mth::sqrt(xd * xd + zd * zd);
|
||||
yRotO = this->yRot = (float) (Mth::atan2(xd, zd) * 180 / Mth::PI);
|
||||
xRotO = this->xRot = (float) (Mth::atan2(yd, sd) * 180 / Mth::PI);
|
||||
}
|
||||
}
|
||||
|
||||
void Throwable::tick() {
|
||||
xOld = x;
|
||||
yOld = y;
|
||||
zOld = z;
|
||||
super::tick();
|
||||
|
||||
if (shakeTime > 0) shakeTime--;
|
||||
|
||||
if (inGround) {
|
||||
// xd = 0;
|
||||
// yd = 0;
|
||||
// zd = 0;
|
||||
int tile = level->getTile(xTile, yTile, zTile);
|
||||
if (tile != lastTile) {
|
||||
inGround = false;
|
||||
|
||||
xd *= sharedRandom.nextFloat() * 0.2f;
|
||||
yd *= sharedRandom.nextFloat() * 0.2f;
|
||||
zd *= sharedRandom.nextFloat() * 0.2f;
|
||||
life = 0;
|
||||
flightTime = 0;
|
||||
} else {
|
||||
life++;
|
||||
if (life == 20 * 60)
|
||||
remove();
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
flightTime++;
|
||||
}
|
||||
|
||||
Vec3 from(x, y, z);
|
||||
Vec3 to(x + xd, y + yd, z + zd);
|
||||
HitResult res = level->clip(from, to);
|
||||
|
||||
from.set(x, y, z);
|
||||
to.set(x + xd, y + yd, z + zd);
|
||||
if (res.isHit())
|
||||
to.set(res.pos.x, res.pos.y, res.pos.z);
|
||||
|
||||
if (!level->isClientSide) {
|
||||
Entity* hitEntity = NULL;
|
||||
EntityList& objects = level->getEntities(this, this->bb.expand(xd, yd, zd).grow(1, 1, 1));
|
||||
float nearest = 0;
|
||||
for (unsigned int i = 0; i < objects.size(); i++) {
|
||||
Entity* e = objects[i];
|
||||
if (!e->isPickable() || (e->entityId == ownerId && flightTime < 5)) continue;
|
||||
|
||||
float rr = 0.3f;
|
||||
AABB bb = e->bb.grow(rr, rr, rr);
|
||||
HitResult p = bb.clip(from, to);
|
||||
if (p.isHit()) {
|
||||
float dd = from.distanceTo(p.pos);
|
||||
if (dd < nearest || nearest == 0) {
|
||||
hitEntity = e;
|
||||
nearest = dd;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (hitEntity != NULL)
|
||||
res = HitResult(hitEntity);
|
||||
}
|
||||
|
||||
if (res.isHit())
|
||||
onHit(res);
|
||||
|
||||
x += xd;
|
||||
y += yd;
|
||||
z += zd;
|
||||
|
||||
float sd = Mth::sqrt(xd * xd + zd * zd);
|
||||
yRot = Mth::atan2(xd, zd) * 180 / Mth::PI;
|
||||
xRot = Mth::atan2(yd, sd) * 180 / Mth::PI;
|
||||
|
||||
while (xRot - xRotO < -180)
|
||||
xRotO -= 360;
|
||||
while (xRot - xRotO >= 180)
|
||||
xRotO += 360;
|
||||
|
||||
while (yRot - yRotO < -180)
|
||||
yRotO -= 360;
|
||||
while (yRot - yRotO >= 180)
|
||||
yRotO += 360;
|
||||
|
||||
xRot = xRotO + (xRot - xRotO) * 0.2f;
|
||||
yRot = yRotO + (yRot - yRotO) * 0.2f;
|
||||
|
||||
|
||||
float inertia = 0.99f;
|
||||
float gravity = getGravity();
|
||||
|
||||
if (isInWater()) {
|
||||
for (int i = 0; i < 4; i++) {
|
||||
float s = 1 / 4.0f;
|
||||
level->addParticle("bubble", x - xd * s, y - yd * s, z - zd * s, xd, yd, zd);
|
||||
}
|
||||
inertia = 0.80f;
|
||||
}
|
||||
|
||||
xd *= inertia;
|
||||
yd *= inertia;
|
||||
zd *= inertia;
|
||||
yd -= gravity;
|
||||
|
||||
setPos(x, y, z);
|
||||
}
|
||||
|
||||
float Throwable::getShadowHeightOffs() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
void Throwable::addAdditonalSaveData( CompoundTag* tag ) {
|
||||
tag->putShort("xTile", (short) xTile);
|
||||
tag->putShort("yTile", (short) yTile);
|
||||
tag->putShort("zTile", (short) zTile);
|
||||
tag->putByte("inTile", (char) lastTile);
|
||||
tag->putByte("shake", (char) shakeTime);
|
||||
tag->putByte("inGround", (char) (inGround ? 1 : 0));
|
||||
}
|
||||
|
||||
void Throwable::readAdditionalSaveData( CompoundTag* tag ) {
|
||||
xTile = tag->getShort("xTile");
|
||||
yTile = tag->getShort("yTile");
|
||||
zTile = tag->getShort("zTile");
|
||||
lastTile = tag->getByte("inTile") & 0xff;
|
||||
shakeTime = tag->getByte("shake") & 0xff;
|
||||
inGround = tag->getByte("inGround") == 1;
|
||||
}
|
||||
|
||||
int Throwable::getAuxData() {
|
||||
return ownerId;
|
||||
}
|
||||
63
src/world/entity/projectile/Throwable.h
Executable file
63
src/world/entity/projectile/Throwable.h
Executable file
@@ -0,0 +1,63 @@
|
||||
#ifndef NET_MINECRAFT_WORLD_ENTITY_PROJECTILE__Throwable_H__
|
||||
#define NET_MINECRAFT_WORLD_ENTITY_PROJECTILE__Throwable_H__
|
||||
|
||||
//package net.minecraft.world.entity->projectile;
|
||||
|
||||
class Level;
|
||||
class Mob;
|
||||
class Player;
|
||||
class CompoundTag;
|
||||
|
||||
#include "../Entity.h"
|
||||
|
||||
class HitResult;
|
||||
|
||||
/*abstract*/
|
||||
class Throwable: public Entity
|
||||
{
|
||||
typedef Entity super;
|
||||
public:
|
||||
Throwable(Level* level);
|
||||
Throwable(Level* level, Mob* mob);
|
||||
Throwable(Level* level, float x, float y, float z);
|
||||
|
||||
void shoot(const Vec3& v, float pow, float uncertainty);
|
||||
void shoot(float xd, float yd, float zd, float pow, float uncertainty);
|
||||
|
||||
void tick();
|
||||
void lerpMotion(float xd, float yd, float zd);
|
||||
|
||||
void addAdditonalSaveData(CompoundTag* tag);
|
||||
void readAdditionalSaveData(CompoundTag* tag);
|
||||
|
||||
bool shouldRenderAtSqrDistance(float distance);
|
||||
|
||||
float getShadowHeightOffs();
|
||||
|
||||
int getAuxData();
|
||||
protected:
|
||||
virtual float getThrowPower();
|
||||
virtual float getThrowUpAngleOffset();
|
||||
|
||||
virtual float getGravity();
|
||||
|
||||
virtual void onHit(const HitResult& res) = 0;
|
||||
|
||||
private:
|
||||
void _init();
|
||||
|
||||
public:
|
||||
int shakeTime;
|
||||
protected:
|
||||
bool inGround;
|
||||
int ownerId;
|
||||
private:
|
||||
int life;
|
||||
int flightTime;
|
||||
int xTile;
|
||||
int yTile;
|
||||
int zTile;
|
||||
int lastTile;
|
||||
};
|
||||
|
||||
#endif /*NET_MINECRAFT_WORLD_ENTITY_PROJECTILE__Throwable_H__*/
|
||||
63
src/world/entity/projectile/ThrownEgg.h
Executable file
63
src/world/entity/projectile/ThrownEgg.h
Executable file
@@ -0,0 +1,63 @@
|
||||
#ifndef NET_MINECRAFT_WORLD_ENTITY_PROJECTILE__ThrownEgg_H__
|
||||
#define NET_MINECRAFT_WORLD_ENTITY_PROJECTILE__ThrownEgg_H__
|
||||
|
||||
//package net.minecraft.world.entity->projectile;
|
||||
|
||||
#include "Throwable.h"
|
||||
#include "../Mob.h"
|
||||
#include "../animal/Chicken.h"
|
||||
#include "../../level/Level.h"
|
||||
#include "../../phys/HitResult.h"
|
||||
|
||||
class ThrownEgg: public Throwable
|
||||
{
|
||||
typedef Throwable super;
|
||||
public:
|
||||
ThrownEgg(Level* level)
|
||||
: super(level)
|
||||
{
|
||||
entityRendererId = ER_THROWNEGG_RENDERER;
|
||||
}
|
||||
|
||||
ThrownEgg(Level* level, Mob* mob)
|
||||
: super(level, mob)
|
||||
{
|
||||
entityRendererId = ER_THROWNEGG_RENDERER;
|
||||
}
|
||||
|
||||
ThrownEgg(Level* level, float x, float y, float z)
|
||||
: super(level, x, y, z)
|
||||
{
|
||||
entityRendererId = ER_THROWNEGG_RENDERER;
|
||||
}
|
||||
|
||||
virtual int getEntityTypeId() const {
|
||||
return EntityTypes::IdThrownEgg;
|
||||
}
|
||||
|
||||
/*@Override*/
|
||||
protected:
|
||||
void onHit(const HitResult& res) {
|
||||
if (res.type == ENTITY)
|
||||
res.entity->hurt(this, 0);
|
||||
|
||||
if (!level->isClientSide && sharedRandom.nextInt(8) == 0) {
|
||||
int count = 1;
|
||||
if (sharedRandom.nextInt(32) == 0) count = 4;
|
||||
for (int i = 0; i < count; i++) {
|
||||
Chicken* chicken = new Chicken(level);
|
||||
//chicken.setAge(-20 * 60 * 20);
|
||||
chicken->moveTo(x, y, z, yRot, 0);
|
||||
level->addEntity(chicken);
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < 6; i++)
|
||||
level->addParticle(PARTICLETYPE(snowballpoof), x, y, z, 0, 0, 0);
|
||||
|
||||
if (!level->isClientSide)
|
||||
remove();
|
||||
}
|
||||
};
|
||||
|
||||
#endif /*NET_MINECRAFT_WORLD_ENTITY_PROJECTILE__ThrownEgg_H__*/
|
||||
Reference in New Issue
Block a user