|
|
@@ -245,6 +245,7 @@ Entity::Entity(
|
|
|
lastChunkCenter(0, 0),
|
|
|
lastSavedChunkCenter(Framework::Maybe<Framework::Punkt>::empty()),
|
|
|
lastDimensionId(-1),
|
|
|
+ maxMovementSpeed(0.f),
|
|
|
speed(0, 0, 0),
|
|
|
faceDir(1, 0, 0),
|
|
|
target(0),
|
|
|
@@ -253,7 +254,8 @@ Entity::Entity(
|
|
|
gravityMultiplier(1.f),
|
|
|
jumpSpeed(0.f),
|
|
|
id(entityId),
|
|
|
- placeBlockCooldown(0)
|
|
|
+ placeBlockCooldown(0.0),
|
|
|
+ movementFlags(0)
|
|
|
{}
|
|
|
|
|
|
void Entity::onDeath(Entity* zActor, Item* zUsedItem, ItemSkill* zUsedSkill)
|
|
|
@@ -350,7 +352,7 @@ bool Entity::useItem(int typeId, ItemStack* zStack, bool left)
|
|
|
}
|
|
|
if (result)
|
|
|
{
|
|
|
- placeBlockCooldown = 15;
|
|
|
+ placeBlockCooldown = 1.0;
|
|
|
}
|
|
|
cs.unlock();
|
|
|
return result;
|
|
|
@@ -423,44 +425,13 @@ bool Entity::interact(Item* zItem, Entity* zActor)
|
|
|
return false;
|
|
|
}
|
|
|
|
|
|
-void Entity::addMovementFrame(MovementFrame& frame)
|
|
|
+void Entity::calculateTarget(const Item* zItem)
|
|
|
{
|
|
|
- cs.lock();
|
|
|
- movements.add(frame);
|
|
|
- cs.unlock();
|
|
|
- Dimension* dim = Game::INSTANCE->zDimension(lastDimensionId);
|
|
|
- if (dim)
|
|
|
- {
|
|
|
- Chunk* chunk = dim->zChunk(lastChunkCenter);
|
|
|
- if (chunk)
|
|
|
- {
|
|
|
- NetworkMessage* message = new NetworkMessage();
|
|
|
- message->addressEntity(this);
|
|
|
- char* msg = new char[37];
|
|
|
- msg[0] = 0;
|
|
|
- *(float*)(msg + 1) = frame.direction.x;
|
|
|
- *(float*)(msg + 5) = frame.direction.y;
|
|
|
- *(float*)(msg + 9) = frame.direction.z;
|
|
|
- *(float*)(msg + 13) = frame.targetPosition.x;
|
|
|
- *(float*)(msg + 17) = frame.targetPosition.y;
|
|
|
- *(float*)(msg + 21) = frame.targetPosition.z;
|
|
|
- *(int*)(msg + 25) = frame.movementFlags;
|
|
|
- *(double*)(msg + 29) = frame.duration;
|
|
|
- message->setMessage(msg, 37);
|
|
|
- chunk->notifyObservers(message);
|
|
|
- }
|
|
|
- }
|
|
|
- faceDir = frame.direction;
|
|
|
-}
|
|
|
-
|
|
|
-void Entity::calculateTarget(Framework::Vec3<float> basePos,
|
|
|
- Framework::Vec3<float> direction,
|
|
|
- const Item* zItem)
|
|
|
-{
|
|
|
- Framework::Vec3<float> headPosition = basePos + faceOffset;
|
|
|
+ Framework::Vec3<float> headPosition = location + faceOffset;
|
|
|
int px = (int)floor(headPosition.x);
|
|
|
int py = (int)floor(headPosition.y);
|
|
|
int pz = (int)floor(headPosition.z);
|
|
|
+ Framework::Vec3<float> direction = faceDir;
|
|
|
direction.normalize();
|
|
|
Direction dir = BOTTOM;
|
|
|
bool found = false;
|
|
|
@@ -617,78 +588,555 @@ ItemSkill* Entity::zSkill(int itemType)
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
-void Entity::prepareTick(const Dimension* zDimension) {}
|
|
|
+void Entity::calcBlockCollision(int& x, int& y, int& xl, int& yl, bool** map)
|
|
|
+{
|
|
|
+ Framework::Vec3<float> minXY = -boundingBox;
|
|
|
+ Framework::Vec3<float> maxXY = boundingBox;
|
|
|
+ Framework::Vec3<float> minXmaxY(minXY.x, maxXY.y, minXY.z);
|
|
|
+ Framework::Vec3<float> maxXminY(maxXY.x, minXY.y, minXY.z);
|
|
|
+ maxXY.z = minXY.z;
|
|
|
+ minXY.rotateZ(rotation);
|
|
|
+ maxXY.rotateZ(rotation);
|
|
|
+ minXmaxY.rotateZ(rotation);
|
|
|
+ maxXminY.rotateZ(rotation);
|
|
|
+ minXY += location;
|
|
|
+ maxXY += location;
|
|
|
+ minXmaxY += location;
|
|
|
+ maxXminY += location;
|
|
|
+ x = (int)minXY.x;
|
|
|
+ y = (int)minXY.y;
|
|
|
+ if (x > (int)minXmaxY.x) x = (int)minXmaxY.x;
|
|
|
+ if (x > (int)maxXminY.x) x = (int)maxXminY.x;
|
|
|
+ if (x > (int)maxXY.x) x = (int)maxXY.x;
|
|
|
+ if (y > (int)minXmaxY.y) y = (int)minXmaxY.y;
|
|
|
+ if (y > (int)maxXminY.y) y = (int)maxXminY.y;
|
|
|
+ if (y > (int)maxXY.y) y = (int)maxXY.y;
|
|
|
+ xl = (int)minXY.x;
|
|
|
+ if (xl < (int)minXmaxY.x) xl = (int)minXmaxY.x;
|
|
|
+ if (xl < (int)maxXminY.x) xl = (int)maxXminY.x;
|
|
|
+ if (xl < (int)maxXY.x) xl = (int)maxXY.x;
|
|
|
+ yl = (int)minXY.y;
|
|
|
+ if (yl < (int)minXmaxY.y) yl = (int)minXmaxY.y;
|
|
|
+ if (yl < (int)maxXminY.y) yl = (int)maxXminY.y;
|
|
|
+ if (yl < (int)maxXY.y) yl = (int)maxXY.y;
|
|
|
+ xl = xl - x + 1;
|
|
|
+ yl = yl - y + 1;
|
|
|
+ *map = new bool[xl * yl];
|
|
|
+ memset(*map, 0, xl * yl * sizeof(bool));
|
|
|
+ int xi = (int)minXY.x - x;
|
|
|
+ int yi = (int)minXY.y - y;
|
|
|
+ (*map)[xi + yi * xl] = 1;
|
|
|
+ xi = (int)maxXY.x - x;
|
|
|
+ yi = (int)maxXY.y - y;
|
|
|
+ (*map)[xi + yi * xl] = 1;
|
|
|
+ xi = (int)minXmaxY.x - x;
|
|
|
+ yi = (int)minXmaxY.y - y;
|
|
|
+ (*map)[xi + yi * xl] = 1;
|
|
|
+ xi = (int)maxXminY.x - x;
|
|
|
+ yi = (int)maxXminY.y - y;
|
|
|
+ (*map)[xi + yi * xl] = 1;
|
|
|
+ auto dir = minXmaxY - minXY;
|
|
|
+ float m = 0;
|
|
|
+ if (abs(dir.x) >= abs(dir.y))
|
|
|
+ {
|
|
|
+ if (dir.x != 0 && dir.y != 0)
|
|
|
+ {
|
|
|
+ m = dir.y / dir.x;
|
|
|
+ }
|
|
|
+ float yy = minXY.y;
|
|
|
+ for (int xx = (int)minXY.x; xx < (int)minXmaxY.x; xx++)
|
|
|
+ {
|
|
|
+ int xi = xx - x;
|
|
|
+ int yi = (int)yy - y;
|
|
|
+ (*map)[xi + yi * xl] = 1;
|
|
|
+ yy += m;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ if (dir.x != 0 && dir.y != 0)
|
|
|
+ {
|
|
|
+ m = dir.x / dir.y;
|
|
|
+ }
|
|
|
+ float xx = minXY.x;
|
|
|
+ for (int yy = (int)minXY.y; yy < (int)minXmaxY.y; yy++)
|
|
|
+ {
|
|
|
+ int xi = (int)xx - x;
|
|
|
+ int yi = yy - y;
|
|
|
+ (*map)[xi + yi * xl] = 1;
|
|
|
+ xx += m;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ dir = maxXminY - minXY;
|
|
|
+ m = 0;
|
|
|
+ if (abs(dir.x) >= abs(dir.y))
|
|
|
+ {
|
|
|
+ if (dir.x != 0 && dir.y != 0)
|
|
|
+ {
|
|
|
+ m = dir.y / dir.x;
|
|
|
+ }
|
|
|
+ float yy = minXY.y;
|
|
|
+ for (int xx = (int)minXY.x; xx < (int)maxXminY.x; xx++)
|
|
|
+ {
|
|
|
+ int xi = xx - x;
|
|
|
+ int yi = (int)yy - y;
|
|
|
+ (*map)[xi + yi * xl] = 1;
|
|
|
+ yy += m;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ if (dir.x != 0 && dir.y != 0)
|
|
|
+ {
|
|
|
+ m = dir.x / dir.y;
|
|
|
+ }
|
|
|
+ float xx = minXY.x;
|
|
|
+ for (int yy = (int)minXY.y; yy < (int)maxXminY.y; yy++)
|
|
|
+ {
|
|
|
+ int xi = (int)xx - x;
|
|
|
+ int yi = yy - y;
|
|
|
+ (*map)[xi + yi * xl] = 1;
|
|
|
+ xx += m;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ dir = maxXY - maxXminY;
|
|
|
+ m = 0;
|
|
|
+ if (abs(dir.x) >= abs(dir.y))
|
|
|
+ {
|
|
|
+ if (dir.x != 0 && dir.y != 0)
|
|
|
+ {
|
|
|
+ m = dir.y / dir.x;
|
|
|
+ }
|
|
|
+ float yy = maxXminY.y;
|
|
|
+ for (int xx = (int)maxXminY.x; xx < (int)maxXY.x; xx++)
|
|
|
+ {
|
|
|
+ int xi = xx - x;
|
|
|
+ int yi = (int)yy - y;
|
|
|
+ (*map)[xi + yi * xl] = 1;
|
|
|
+ yy += m;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ if (dir.x != 0 && dir.y != 0)
|
|
|
+ {
|
|
|
+ m = dir.x / dir.y;
|
|
|
+ }
|
|
|
+ float xx = maxXminY.x;
|
|
|
+ for (int yy = (int)maxXminY.y; yy < (int)maxXY.y; yy++)
|
|
|
+ {
|
|
|
+ int xi = (int)xx - x;
|
|
|
+ int yi = yy - y;
|
|
|
+ (*map)[xi + yi * xl] = 1;
|
|
|
+ xx += m;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ dir = maxXY - minXmaxY;
|
|
|
+ m = 0;
|
|
|
+ if (abs(dir.x) >= abs(dir.y))
|
|
|
+ {
|
|
|
+ if (dir.x != 0 && dir.y != 0)
|
|
|
+ {
|
|
|
+ m = dir.y / dir.x;
|
|
|
+ }
|
|
|
+ float yy = minXmaxY.y;
|
|
|
+ for (int xx = (int)minXmaxY.x; xx < (int)maxXY.x; xx++)
|
|
|
+ {
|
|
|
+ int xi = xx - x;
|
|
|
+ int yi = (int)yy - y;
|
|
|
+ (*map)[xi + yi * xl] = 1;
|
|
|
+ yy += m;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ if (dir.x != 0 && dir.y != 0)
|
|
|
+ {
|
|
|
+ m = dir.x / dir.y;
|
|
|
+ }
|
|
|
+ float xx = minXmaxY.x;
|
|
|
+ for (int yy = (int)minXmaxY.y; yy < (int)maxXY.y; yy++)
|
|
|
+ {
|
|
|
+ int xi = (int)xx - x;
|
|
|
+ int yi = yy - y;
|
|
|
+ (*map)[xi + yi * xl] = 1;
|
|
|
+ xx += m;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ for (int yy = 0; yy < yl; yy++)
|
|
|
+ {
|
|
|
+ int min = xl;
|
|
|
+ int max = -1;
|
|
|
+ for (int xx = 0; xx < xl; xx++)
|
|
|
+ {
|
|
|
+ if ((*map)[xx + yy * xl])
|
|
|
+ {
|
|
|
+ if (xx < min) min = xx;
|
|
|
+ if (xx > max) max = xx;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ for (int xx = min; xx <= max; xx++)
|
|
|
+ {
|
|
|
+ (*map)[xx + yy * xl] = 1;
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+bool Entity::isCollidingWithBlock(const Dimension* zDimension)
|
|
|
+{
|
|
|
+ int x, y, xl, yl;
|
|
|
+ bool* map;
|
|
|
+ calcBlockCollision(x, y, xl, yl, &map);
|
|
|
+ bool result = isCollidingWithBlock(zDimension, x, y, xl, yl, map);
|
|
|
+ delete[] map;
|
|
|
+ return result;
|
|
|
+}
|
|
|
+
|
|
|
+bool Entity::isCollidingWithBlock(
|
|
|
+ const Dimension* zDimension, int x, int y, int xl, int yl, bool* map)
|
|
|
+{
|
|
|
+ for (int yy = 0; yy < yl; yy++)
|
|
|
+ {
|
|
|
+ for (int xx = 0; xx < xl; xx++)
|
|
|
+ {
|
|
|
+ if (map[xx + yy * xl])
|
|
|
+ {
|
|
|
+ for (int zz = (int)(location.z - boundingBox.z);
|
|
|
+ zz <= (int)(location.z + boundingBox.z);
|
|
|
+ zz++)
|
|
|
+ {
|
|
|
+ const Block* block = zDimension->zBlockOrDefault(
|
|
|
+ Framework::Vec3<int>(x + xx, y + yy, zz));
|
|
|
+ if (!block->isPassable())
|
|
|
+ {
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return false;
|
|
|
+}
|
|
|
|
|
|
-void Entity::tick(const Dimension* zDimension)
|
|
|
+void Entity::prepareTick(const Dimension* zDimension, double seconds) {}
|
|
|
+
|
|
|
+void Entity::tick(const Dimension* zDimension, double seconds)
|
|
|
{
|
|
|
if (removed) return;
|
|
|
if (placeBlockCooldown > 0)
|
|
|
{
|
|
|
- placeBlockCooldown--;
|
|
|
+ placeBlockCooldown -= seconds;
|
|
|
+ }
|
|
|
+ bool changed = 0;
|
|
|
+ float rotSpeed = 0.f;
|
|
|
+ if (movementFlags & MovementFlags::ROTATE_LEFT)
|
|
|
+ {
|
|
|
+ rotSpeed += 3.f * (float)seconds;
|
|
|
+ }
|
|
|
+ if (movementFlags & MovementFlags::ROTATE_RIGHT)
|
|
|
+ {
|
|
|
+ rotSpeed -= 3.f * (float)seconds;
|
|
|
}
|
|
|
- placeBlockCooldown--;
|
|
|
- if (time.isMeasuring())
|
|
|
+ if (movementFlags & MovementFlags::ROTATE_TO_FACE)
|
|
|
{
|
|
|
- time.messungEnde();
|
|
|
- if (movements.getEintragAnzahl() > 0)
|
|
|
+ float rot = Framework::Vec2<float>(0, -1).angle({faceDir.x, faceDir.y});
|
|
|
+ rotSpeed = rot - rotation;
|
|
|
+ }
|
|
|
+ if (rotSpeed != 0.f)
|
|
|
+ {
|
|
|
+ rotation += rotSpeed;
|
|
|
+ if (isCollidingWithBlock(zDimension))
|
|
|
+ {
|
|
|
+ rotation -= rotSpeed;
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ changed = 1;
|
|
|
+ }
|
|
|
+ while (rotation > 2.f * (float)PI)
|
|
|
{
|
|
|
- MovementFrame currentFrame = movements.get(0);
|
|
|
- double seconds = time.getSekunden();
|
|
|
- while (seconds > 0)
|
|
|
+ rotation -= 2.f * (float)PI;
|
|
|
+ }
|
|
|
+ while (rotation < 0.f)
|
|
|
+ {
|
|
|
+ rotation += 2.f * (float)PI;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ Framework::Vec3<float> moveDir(0.f, 0.f, 0.f);
|
|
|
+ if (movementFlags & MovementFlags::WALK_FORWARD)
|
|
|
+ {
|
|
|
+ moveDir.x += cosf(rotation - (float)PI / 2.f);
|
|
|
+ moveDir.y += sinf(rotation - (float)PI / 2.f);
|
|
|
+ }
|
|
|
+ if (movementFlags & MovementFlags::WALK_BACKWARD)
|
|
|
+ {
|
|
|
+ moveDir.x -= cosf(rotation - (float)PI / 2.f);
|
|
|
+ moveDir.y -= sinf(rotation - (float)PI / 2.f);
|
|
|
+ }
|
|
|
+ if (movementFlags & MovementFlags::WALK_LEFT)
|
|
|
+ {
|
|
|
+ moveDir.x += cosf(rotation + (float)PI);
|
|
|
+ moveDir.y += sinf(rotation + (float)PI);
|
|
|
+ }
|
|
|
+ if (movementFlags & MovementFlags::WALK_RIGHT)
|
|
|
+ {
|
|
|
+ moveDir.x += cosf(rotation);
|
|
|
+ moveDir.y += sinf(rotation);
|
|
|
+ }
|
|
|
+ if (movementFlags & MovementFlags::FLYING
|
|
|
+ && movementFlags & MovementFlags::JUMPING)
|
|
|
+ {
|
|
|
+ moveDir.z += 1.f;
|
|
|
+ movementFlags &= ~MovementFlags::GROUND_CONTACT;
|
|
|
+ }
|
|
|
+ if (movementFlags & MovementFlags::FLYING
|
|
|
+ && movementFlags & MovementFlags::SNEAKING)
|
|
|
+ {
|
|
|
+ moveDir.z -= 1.f;
|
|
|
+ }
|
|
|
+ float staminaCost = 0.f;
|
|
|
+ if (moveDir.x != 0.f || moveDir.y != 0.f)
|
|
|
+ {
|
|
|
+ moveDir.normalize();
|
|
|
+ moveDir *= maxMovementSpeed * (float)seconds;
|
|
|
+ if (movementFlags & MovementFlags::SPRINTING)
|
|
|
+ {
|
|
|
+ moveDir *= 2.f;
|
|
|
+ }
|
|
|
+ if (movementFlags & MovementFlags::SNEAKING
|
|
|
+ && !(movementFlags & MovementFlags::FLYING))
|
|
|
+ {
|
|
|
+ moveDir *= 0.5f;
|
|
|
+ }
|
|
|
+ staminaCost = moveDir.getLength() / (maxMovementSpeed * 10);
|
|
|
+ if (stamina < staminaCost)
|
|
|
+ {
|
|
|
+ staminaCost = stamina;
|
|
|
+ moveDir *= stamina / staminaCost;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if (!(movementFlags & MovementFlags::FLYING)
|
|
|
+ && movementFlags & MovementFlags::JUMPING
|
|
|
+ && movementFlags & MovementFlags::GROUND_CONTACT)
|
|
|
+ {
|
|
|
+ if (stamina > staminaCost + 0.02f)
|
|
|
+ {
|
|
|
+ staminaCost += 0.02f;
|
|
|
+ speed.z += jumpSpeed;
|
|
|
+ movementFlags &= ~MovementFlags::GROUND_CONTACT;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if (!(movementFlags & MovementFlags::FLYING))
|
|
|
+ {
|
|
|
+ speed.z
|
|
|
+ -= zDimension->getGravity() * gravityMultiplier * (float)seconds;
|
|
|
+ }
|
|
|
+ moveDir += speed * (float)seconds;
|
|
|
+ bool staminaChanged = staminaCost != 0.f;
|
|
|
+ stamina -= staminaCost;
|
|
|
+ if (stamina <= maxStamina - (float)seconds)
|
|
|
+ {
|
|
|
+ if (getThirst() > 0 && getHunger() > 0)
|
|
|
+ { // TODO: modify regen rate based on hunger/thirst
|
|
|
+ stamina += (float)seconds;
|
|
|
+ staminaChanged = 1;
|
|
|
+ setHunger(hunger - (float)seconds / 5.f);
|
|
|
+ setThirst(thirst - (float)seconds / 2.5f);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if (staminaChanged)
|
|
|
+ {
|
|
|
+ setStamina(stamina); // notify observers
|
|
|
+ }
|
|
|
+ if (moveDir.x != 0.f || moveDir.y != 0.f || moveDir.z != 0.f)
|
|
|
+ {
|
|
|
+ while (abs(moveDir.x) > 1.f)
|
|
|
+ {
|
|
|
+ if (moveDir.x > 0.f)
|
|
|
{
|
|
|
- if (currentFrame.duration <= 0)
|
|
|
+ location.x += 1.f;
|
|
|
+ if (isCollidingWithBlock(zDimension))
|
|
|
{
|
|
|
- cs.lock();
|
|
|
- movements.remove(0);
|
|
|
- cs.unlock();
|
|
|
- if (movements.getEintragAnzahl() > 0)
|
|
|
- currentFrame = movements.get(0);
|
|
|
- else
|
|
|
- break;
|
|
|
+ moveDir.x = 0.f;
|
|
|
+ speed.x = 0.f;
|
|
|
+ location.x -= 1.f;
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ moveDir.x -= 1.f;
|
|
|
+ changed = 1;
|
|
|
}
|
|
|
- double t = MIN(currentFrame.duration, seconds);
|
|
|
- // TODO: add collision detection to reduce cheating capability
|
|
|
- location += (currentFrame.targetPosition - location)
|
|
|
- * (float)(t / currentFrame.duration);
|
|
|
- currentFrame.duration -= t;
|
|
|
- seconds -= t;
|
|
|
- if (currentFrame.duration <= 0)
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ location.x -= 1.f;
|
|
|
+ if (isCollidingWithBlock(zDimension))
|
|
|
+ {
|
|
|
+ moveDir.x = 0.f;
|
|
|
+ speed.x = 0.f;
|
|
|
+ location.x += 1.f;
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ moveDir.x += 1.f;
|
|
|
+ changed = 1;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if (moveDir.x != 0.f)
|
|
|
+ {
|
|
|
+ location.x += moveDir.x;
|
|
|
+ if (isCollidingWithBlock(zDimension))
|
|
|
+ {
|
|
|
+ location.x -= moveDir.x;
|
|
|
+ speed.x = 0.f;
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ changed = 1;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ while (abs(moveDir.y) > 1.f)
|
|
|
+ {
|
|
|
+ if (moveDir.y > 0.f)
|
|
|
+ {
|
|
|
+ location.y += 1.f;
|
|
|
+ if (isCollidingWithBlock(zDimension))
|
|
|
+ {
|
|
|
+ moveDir.y = 0.f;
|
|
|
+ location.y -= 1.f;
|
|
|
+ speed.y = 0.f;
|
|
|
+ }
|
|
|
+ else
|
|
|
{
|
|
|
- location = currentFrame.targetPosition;
|
|
|
+ moveDir.y -= 1.f;
|
|
|
+ changed = 1;
|
|
|
}
|
|
|
}
|
|
|
- if (currentFrame.duration > 0) movements.set(currentFrame, 0);
|
|
|
- if (getStamina() <= getMaxStamina() - 0.0025f)
|
|
|
+ else
|
|
|
{
|
|
|
- if (getThirst() > 0 && getHunger() > 0)
|
|
|
+ location.y -= 1.f;
|
|
|
+ if (isCollidingWithBlock(zDimension))
|
|
|
{
|
|
|
- setStamina(getStamina() + 0.0025f);
|
|
|
- setHunger(getHunger() - 0.0005f);
|
|
|
- setThirst(getThirst() - 0.0015f);
|
|
|
+ moveDir.y = 0.f;
|
|
|
+ location.y += 1.f;
|
|
|
+ speed.y = 0.f;
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ moveDir.y += 1.f;
|
|
|
+ changed = 1;
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
- else
|
|
|
+ if (moveDir.y != 0.f)
|
|
|
+ {
|
|
|
+ location.y += moveDir.y;
|
|
|
+ if (isCollidingWithBlock(zDimension))
|
|
|
+ {
|
|
|
+ location.y -= moveDir.y;
|
|
|
+ speed.y = 0.f;
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ changed = 1;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ while (abs(moveDir.z) > 1.f)
|
|
|
+ {
|
|
|
+ if (moveDir.z > 0.f)
|
|
|
+ {
|
|
|
+ location.z += 1.f;
|
|
|
+ if (isCollidingWithBlock(zDimension))
|
|
|
+ {
|
|
|
+ moveDir.z = 0.f;
|
|
|
+ location.z -= 1.f;
|
|
|
+ speed.z = 0.f;
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ moveDir.z -= 1.f;
|
|
|
+ changed = 1;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ location.z -= 1.f;
|
|
|
+ if (isCollidingWithBlock(zDimension))
|
|
|
+ {
|
|
|
+ moveDir.z = 0.f;
|
|
|
+ location.z += 1.f;
|
|
|
+ onFall(speed.z);
|
|
|
+ speed.z = 0.f;
|
|
|
+ movementFlags |= MovementFlags::GROUND_CONTACT;
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ moveDir.z += 1.f;
|
|
|
+ changed = 1;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if (moveDir.z != 0.f)
|
|
|
{
|
|
|
- if (getStamina() <= getMaxStamina() - 0.005f)
|
|
|
+ location.z += moveDir.z;
|
|
|
+ if (isCollidingWithBlock(zDimension))
|
|
|
{
|
|
|
- if (getThirst() > 0 && getHunger() > 0)
|
|
|
+ if (speed.z < 0.f)
|
|
|
{
|
|
|
- setStamina(getStamina() + 0.005f);
|
|
|
- setHunger(getHunger() - 0.001f);
|
|
|
- setThirst(getThirst() - 0.003f);
|
|
|
+ onFall(speed.z);
|
|
|
+ speed.z = 0.f;
|
|
|
+ movementFlags |= MovementFlags::GROUND_CONTACT;
|
|
|
}
|
|
|
+ else
|
|
|
+ {
|
|
|
+ changed = 1;
|
|
|
+ }
|
|
|
+ location.z -= moveDir.z;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if (movementFlags & MovementFlags::GROUND_CONTACT)
|
|
|
+ {
|
|
|
+ if (speed.x != 0)
|
|
|
+ {
|
|
|
+ if (speed.x > (float)seconds)
|
|
|
+ {
|
|
|
+ speed.x -= (float)seconds;
|
|
|
+ }
|
|
|
+ else if (speed.x < -(float)seconds)
|
|
|
+ {
|
|
|
+ speed.x += (float)seconds;
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ speed.x = 0;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if (speed.y != 0)
|
|
|
+ {
|
|
|
+ if (speed.y > (float)seconds)
|
|
|
+ {
|
|
|
+ speed.y -= (float)seconds;
|
|
|
+ }
|
|
|
+ else if (speed.y < -(float)seconds)
|
|
|
+ {
|
|
|
+ speed.y += (float)seconds;
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ speed.y = 0;
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
- time.messungStart();
|
|
|
Framework::Punkt chunkCenter
|
|
|
= Game::INSTANCE->getChunkCenter((int)location.x, (int)location.y);
|
|
|
+ Chunk* zCurrentChunk = 0;
|
|
|
if (dimensionId != lastDimensionId || chunkCenter != lastChunkCenter)
|
|
|
{
|
|
|
Dimension* lastDimension = Game::INSTANCE->zDimension(lastDimensionId);
|
|
|
Dimension* currentDimension = Game::INSTANCE->zDimension(dimensionId);
|
|
|
- Chunk* zCurrentChunk
|
|
|
+ zCurrentChunk
|
|
|
= currentDimension ? currentDimension->zChunk(chunkCenter) : 0;
|
|
|
Chunk* zLastChunk
|
|
|
= lastDimension ? lastDimension->zChunk(lastChunkCenter) : 0;
|
|
|
@@ -708,6 +1156,22 @@ void Entity::tick(const Dimension* zDimension)
|
|
|
lastDimensionId = dimensionId;
|
|
|
lastChunkCenter = chunkCenter;
|
|
|
}
|
|
|
+ if (changed)
|
|
|
+ {
|
|
|
+ if (!zCurrentChunk)
|
|
|
+ {
|
|
|
+ Dimension* currentDimension
|
|
|
+ = Game::INSTANCE->zDimension(dimensionId);
|
|
|
+ zCurrentChunk
|
|
|
+ = currentDimension ? currentDimension->zChunk(chunkCenter) : 0;
|
|
|
+ }
|
|
|
+ if (zCurrentChunk)
|
|
|
+ {
|
|
|
+ NetworkMessage* msg = new NetworkMessage();
|
|
|
+ msg->sendEntityMovement(this, (float)seconds);
|
|
|
+ zCurrentChunk->notifyObservers(msg);
|
|
|
+ }
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
void Entity::api(Framework::StreamReader* zRequest,
|
|
|
@@ -763,9 +1227,9 @@ void Entity::api(Framework::StreamReader* zRequest,
|
|
|
|
|
|
void Entity::onFall(float collisionSpeed)
|
|
|
{
|
|
|
- if (collisionSpeed > 10)
|
|
|
+ if (collisionSpeed > 20)
|
|
|
{
|
|
|
- setHP(this, 0, 0, getCurrentHP() - (collisionSpeed - 10.f) / 2.5f);
|
|
|
+ setHP(this, 0, 0, getCurrentHP() - (collisionSpeed - 20.f) / 2.5f);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
@@ -964,7 +1428,7 @@ float Entity::getMaxSpeed() const
|
|
|
|
|
|
bool Entity::isMoving() const
|
|
|
{
|
|
|
- return movements.getEintragAnzahl() > 0;
|
|
|
+ return movementFlags > 0;
|
|
|
}
|
|
|
|
|
|
int Entity::getChatSecurityLevel() const
|
|
|
@@ -990,12 +1454,10 @@ void Entity::setRemoved()
|
|
|
double Entity::getHitDistance(
|
|
|
Framework::Vec3<float> rayOrigin, Framework::Vec3<float> rayDirection) const
|
|
|
{
|
|
|
- Framework::Mat4<float> rotMat
|
|
|
- = Framework::Mat4<float>::rotationX(-rotation.x)
|
|
|
- * Framework::Mat4<float>::rotationY(-rotation.y)
|
|
|
- * Framework::Mat4<float>::rotationZ(-rotation.z);
|
|
|
- Framework::Vec3<float> rotatedRayOrigin = rotMat * rayOrigin;
|
|
|
- Framework::Vec3<float> rotatedRayDirection = rotMat * rayDirection;
|
|
|
+ Framework::Vec3<float> rotatedRayOrigin
|
|
|
+ = Framework::Vec3<float>(rayOrigin).rotateZ(-rotation);
|
|
|
+ Framework::Vec3<float> rotatedRayDirection
|
|
|
+ = Framework::Vec3<float>(rayDirection).rotateZ(-rotation);
|
|
|
rotatedRayDirection.normalize();
|
|
|
if (rotatedRayDirection.x != 0)
|
|
|
{
|
|
|
@@ -1077,3 +1539,8 @@ double Entity::getHitDistance(
|
|
|
}
|
|
|
return NAN;
|
|
|
}
|
|
|
+
|
|
|
+float Entity::getRotation() const
|
|
|
+{
|
|
|
+ return rotation;
|
|
|
+}
|