#include "Entity.h" #include "Dimension.h" #include "Game.h" #include "BlockType.h" Entity::Entity( const EntityType* zType, Framework::Vec3 location, int dimensionId, int entityId ) : Inventory( location, true ), speed( 0, 0, 0 ), faceDir( 1, 0, 0 ), zEntityType( zType ), currentDimensionId( dimensionId ), removed( 0 ), gravityMultiplier( 1.f ), id( entityId ) {} void Entity::onDeath() {} void Entity::tick( const Dimension* zDimension, Game* zGame ) { Vec3 oldPos = location; // current block cooredinates int px = (int)floor( location.x ); int py = (int)floor( location.y ); int pz = (int)floor( location.z ); // falling down speed.z -= (zDimension->getGravity() * gravityMultiplier) / 30.f; // movement in current tick Vec3 frameSpeed = speed / 30.f; // loop through all collided blocks bool needCollisionCheck = 1; while( needCollisionCheck ) { needCollisionCheck = 0; // collision to neighbor of current block current block if( speed.x > 0 ) { float xt = ((float)px + 1.f - oldPos.x) / frameSpeed.x; Vec3 tmp = oldPos + frameSpeed * xt; if( xt <= 1.f && tmp.y >= (float)py && tmp.y < (float)py + 1.f && tmp.z >= (float)pz && tmp.z < (float)pz + 1.f ) { if( !getDefaultBlock( zGame->zBlockAt( Vec3{ px + 1, py, pz }, zDimension->getDimensionId() ) )->isPassable() ) { frameSpeed.x = frameSpeed.x * (xt - 0.1f); speed.x = 0; } else px++; needCollisionCheck = 1; continue; } } if( speed.x < 0 ) { float xt = ((float)px - oldPos.x) / frameSpeed.x; Vec3 tmp = oldPos + frameSpeed * xt; if( xt <= 1.f && tmp.y >= (float)py && tmp.y < (float)py + 1.f && tmp.z >= (float)pz && tmp.z < (float)pz + 1.f ) { if( !getDefaultBlock( zGame->zBlockAt( Vec3{ px - 1, py, pz }, zDimension->getDimensionId() ) )->isPassable() ) { frameSpeed.x = frameSpeed.x * (xt - 0.1f); speed.x = 0; } else px--; needCollisionCheck = 1; continue; } } if( speed.y > 0 ) { float yt = ((float)py + 1.f - oldPos.y) / frameSpeed.y; Vec3 tmp = oldPos + frameSpeed * yt; if( yt <= 1.f && tmp.x >= (float)px && tmp.x < (float)px + 1.f && tmp.z >= (float)pz && tmp.z < (float)pz + 1.f ) { if( !getDefaultBlock( zGame->zBlockAt( Vec3{ px, py + 1, pz }, zDimension->getDimensionId() ) )->isPassable() ) { frameSpeed.y = frameSpeed.y * (yt - 0.1f); speed.y = 0; } else py++; needCollisionCheck = 1; continue; } } if( speed.y < 0 ) { float yt = ((float)py - oldPos.y) / frameSpeed.y; Vec3 tmp = oldPos + frameSpeed * yt; if( yt <= 1.f && tmp.x >= (float)px && tmp.x < (float)px + 1.f && tmp.z >= (float)pz && tmp.z < (float)pz + 1.f ) { if( !getDefaultBlock( zGame->zBlockAt( Vec3{ px, py - 1, pz }, zDimension->getDimensionId() ) )->isPassable() ) { frameSpeed.y = frameSpeed.y * (yt - 0.1f); speed.y = 0; } else py--; needCollisionCheck = 1; continue; } } if( speed.z > 0 ) { float zt = ((float)pz + 1.f - oldPos.z) / frameSpeed.z; Vec3 tmp = oldPos + frameSpeed * zt; if( zt <= 1.f && tmp.x >= (float)px && tmp.x < (float)px + 1.f && tmp.y >= (float)py && tmp.y < (float)py + 1.f ) { if( !getDefaultBlock( zGame->zBlockAt( Vec3{ px, py, pz + 1 }, zDimension->getDimensionId() ) )->isPassable() ) { frameSpeed.z = frameSpeed.z * (zt - 0.1f); speed.z = 0; } else pz++; needCollisionCheck = 1; continue; } } if( speed.z < 0 ) { float zt = ((float)pz - oldPos.z) / frameSpeed.z; Vec3 tmp = oldPos + frameSpeed * zt; if( zt <= 1.f && tmp.x >= (float)px && tmp.x < (float)px + 1.f && tmp.y >= (float)py && tmp.y < (float)py + 1 ) { if( !getDefaultBlock( zGame->zBlockAt( Vec3{ px, py, pz - 1 }, zDimension->getDimensionId() ) )->isPassable() ) { frameSpeed.z = frameSpeed.z * (zt - 0.1f); onFall( speed.z ); speed.z = 0; } else pz--; needCollisionCheck = 1; continue; } } } location += frameSpeed; } void Entity::api( Framework::StreamReader* zRequest, NetworkResponse* zResponse ) { // TODO: answer api requests } void Entity::onFall( float collisionSpeed ) { if( collisionSpeed > 5 ) { // TODO: take damage } } void Entity::setPosition( Framework::Vec3 pos ) { location = pos; } float Entity::getMaxHP() const { return maxHP; } float Entity::getCurrentHP() const { return currentHP; } float Entity::getStamina() const { return stamina; } float Entity::getMaxStamina() const { return maxStamina; } float Entity::getHunger() const { return hunger; } float Entity::getMaxHunger() const { return maxHunger; } float Entity::getThirst() const { return thirst; } float Entity::getMaxThirst() const { return maxThirst; } Framework::Vec3 Entity::getSpeed() const { return speed; } Framework::Vec3 Entity::getFaceDir() const { return faceDir; } Framework::Vec3 Entity::getPosition() const { return location; } float Entity::getGravityMultiplier() const { return gravityMultiplier; } int Entity::getCurrentDimensionId() const { return currentDimensionId; } bool Entity::isRemoved() const { return removed; } const EntityType* Entity::zType() const { return zEntityType; } int Entity::getId() const { return id; }