mirror of
https://gitea.sffempire.ru/Kolyah35/minecraft-pe-0.6.1.git
synced 2026-03-31 12:33:38 +00:00
the whole game
This commit is contained in:
248
src/world/entity/PathfinderMob.cpp
Executable file
248
src/world/entity/PathfinderMob.cpp
Executable file
@@ -0,0 +1,248 @@
|
||||
#include "PathfinderMob.h"
|
||||
#include "../level/Level.h"
|
||||
#include "../phys/Vec3.h"
|
||||
#include "../../util/Mth.h"
|
||||
#include "../../util/PerfTimer.h"
|
||||
#include "../../SharedConstants.h"
|
||||
|
||||
#include "ai/Sensing.h"
|
||||
|
||||
|
||||
PathfinderMob::PathfinderMob( Level* level )
|
||||
: super(level),
|
||||
//navigation(this, level, 16),
|
||||
attackTargetId(0),
|
||||
holdGround(false),
|
||||
fleeTime(0)//,
|
||||
//pathfinderMask(0)
|
||||
{
|
||||
sensing = new Sensing(this);
|
||||
navigation = new PathNavigation(this, level, 16);
|
||||
}
|
||||
|
||||
PathfinderMob::~PathfinderMob() {
|
||||
delete navigation;
|
||||
delete sensing;
|
||||
}
|
||||
|
||||
bool PathfinderMob::canSpawn()
|
||||
{
|
||||
return super::canSpawn() && getWalkTargetValue(Mth::floor(x), Mth::floor(bb.y0), Mth::floor(z)) >= 0;
|
||||
}
|
||||
|
||||
bool PathfinderMob::isPathFinding()
|
||||
{
|
||||
return !path.isEmpty();
|
||||
}
|
||||
|
||||
void PathfinderMob::setPath( Path& path )
|
||||
{
|
||||
this->path = path;
|
||||
}
|
||||
|
||||
Entity* PathfinderMob::getAttackTarget()
|
||||
{
|
||||
if (attackTargetId == 0) return NULL;
|
||||
return level->getEntity(attackTargetId);
|
||||
}
|
||||
|
||||
void PathfinderMob::setAttackTarget( Entity* attacker )
|
||||
{
|
||||
attackTargetId = attacker? attacker->entityId : 0;
|
||||
}
|
||||
|
||||
bool PathfinderMob::shouldHoldGround()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
void PathfinderMob::updateAi()
|
||||
{
|
||||
TIMER_PUSH("ai");
|
||||
|
||||
if (fleeTime > 0) fleeTime--;
|
||||
holdGround = shouldHoldGround();
|
||||
float maxDist = 16;
|
||||
|
||||
Entity* attackTarget = NULL;
|
||||
if (attackTargetId == 0) {
|
||||
attackTarget = findAttackTarget();
|
||||
if (attackTarget != NULL) {
|
||||
level->findPath(&path, this, attackTarget, maxDist, false, false);//(pathfinderMask&CAN_OPEN_DOORS) != 0, (pathfinderMask&AVOID_WATER) != 0);
|
||||
attackTargetId = attackTarget->entityId;
|
||||
//LOGI("path.empty: %d\n", path.isEmpty());
|
||||
}
|
||||
} else {
|
||||
attackTarget = level->getEntity(attackTargetId);
|
||||
if (!attackTarget || !attackTarget->isAlive()) {
|
||||
attackTargetId = 0;
|
||||
attackTarget = NULL;
|
||||
} else {
|
||||
attackTargetId = attackTarget->entityId;
|
||||
float d = attackTarget->distanceTo(this);
|
||||
if (canSee(attackTarget)) {
|
||||
checkHurtTarget(attackTarget, d);
|
||||
} else {
|
||||
checkCantSeeTarget(attackTarget, d);
|
||||
}
|
||||
}
|
||||
}
|
||||
TIMER_POP();
|
||||
|
||||
/*
|
||||
* if (holdGround) { xxa = 0; yya = 0; jumping = false; return; }
|
||||
*/
|
||||
|
||||
bool doStroll = false;
|
||||
if (!holdGround && (attackTarget != NULL && (path.isEmpty() || random.nextInt(20) == 0))) {
|
||||
level->findPath(&path, this, attackTarget, maxDist, false, false);//(pathfinderMask&CAN_OPEN_DOORS) != 0, (pathfinderMask&AVOID_WATER) != 0);
|
||||
} else if (!holdGround) {
|
||||
if (path.isEmpty() && (random.nextInt(180) == 0)) {
|
||||
doStroll = true;
|
||||
} else {
|
||||
if (random.nextInt(120) == 0) doStroll = true;
|
||||
else if (fleeTime > 0 && (fleeTime&7) == 1) doStroll = true;
|
||||
}
|
||||
}
|
||||
if (doStroll) {
|
||||
if (noActionTime < SharedConstants::TicksPerSecond * 5) {
|
||||
findRandomStrollLocation();
|
||||
}
|
||||
}
|
||||
|
||||
int yFloor = Mth::floor(bb.y0 + .5f);
|
||||
|
||||
bool inWater = isInWater();
|
||||
bool inLava = isInLava();
|
||||
xRot = 0;
|
||||
if (path.isEmpty() || random.nextInt(100) == 0) {
|
||||
//super::serverAiStep();
|
||||
super::updateAi();
|
||||
return;
|
||||
}
|
||||
|
||||
TIMER_PUSH("followpath");
|
||||
Vec3 target = path.currentPos(this);
|
||||
float r = bbWidth * 2;
|
||||
bool looping = true;
|
||||
while (looping && target.distanceToSqr(x, target.y, z) < r * r) {
|
||||
path.next();
|
||||
if (path.isDone()) {
|
||||
looping = false;
|
||||
path.destroy();
|
||||
} else target = path.currentPos(this);
|
||||
}
|
||||
|
||||
jumping = false;
|
||||
if (looping) {
|
||||
float xd = target.x - x;
|
||||
float zd = target.z - z;
|
||||
float yd = target.y - yFloor;
|
||||
// float yRotOld = yRot;
|
||||
float yRotD = (float) (Mth::atan2(zd, xd) * 180 / Mth::PI) - 90;
|
||||
float rotDiff = yRotD - yRot;
|
||||
yya = runSpeed;
|
||||
while (rotDiff < -180)
|
||||
rotDiff += 360;
|
||||
while (rotDiff >= 180)
|
||||
rotDiff -= 360;
|
||||
if (rotDiff > MAX_TURN) {
|
||||
rotDiff = MAX_TURN;
|
||||
// yya *= 0.2;
|
||||
}
|
||||
if (rotDiff < -MAX_TURN) {
|
||||
rotDiff = -MAX_TURN;
|
||||
// yya *= 0.2;
|
||||
}
|
||||
yRot += rotDiff;
|
||||
|
||||
if (holdGround) {
|
||||
if (attackTarget != NULL) {
|
||||
float xd2 = attackTarget->x - x;
|
||||
float zd2 = attackTarget->z - z;
|
||||
|
||||
float oldyRot = yRot;
|
||||
yRot = (float) (Mth::atan2(zd2, xd2) * 180 / Mth::PI) - 90;
|
||||
|
||||
rotDiff = ((oldyRot - yRot) + 90) * Mth::PI / 180;
|
||||
xxa = -Mth::sin(rotDiff) * yya * 1.0f;
|
||||
yya = Mth::cos(rotDiff) * yya * 1.0f;
|
||||
}
|
||||
}
|
||||
if (yd > 0) {
|
||||
jumping = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (attackTarget != NULL) {
|
||||
lookAt(attackTarget, 30, 30);
|
||||
}
|
||||
|
||||
if (this->horizontalCollision && !isPathFinding()) jumping = true;
|
||||
if (random.nextFloat() < 0.8f && (inWater || inLava)) jumping = true;
|
||||
|
||||
TIMER_POP();
|
||||
}
|
||||
|
||||
void PathfinderMob::findRandomStrollLocation()
|
||||
{
|
||||
TIMER_PUSH("stroll");
|
||||
bool hasBest = false;
|
||||
int xBest = -1;
|
||||
int yBest = -1;
|
||||
int zBest = -1;
|
||||
float best = -99999;
|
||||
for (int i = 0; i < 10; i++) {
|
||||
int xt = Mth::floor(x + random.nextInt(13) - 6);
|
||||
int yt = Mth::floor(y + random.nextInt(7) - 3);
|
||||
int zt = Mth::floor(z + random.nextInt(13) - 6);
|
||||
float value = getWalkTargetValue(xt, yt, zt);
|
||||
if (value > best) {
|
||||
best = value;
|
||||
xBest = xt;
|
||||
yBest = yt;
|
||||
zBest = zt;
|
||||
hasBest = true;
|
||||
}
|
||||
|
||||
}
|
||||
if (hasBest) {
|
||||
//LOGI("Finding a new strolling location! %d, %d, %d (%d, %d, %d) for %p\n", xBest, yBest, zBest, (int)x, (int)y, (int)z, this);
|
||||
level->findPath(&path, this, xBest, yBest, zBest, 10, false, false);//(pathfinderMask&CAN_OPEN_DOORS) != 0, (pathfinderMask&AVOID_WATER) != 0);
|
||||
}
|
||||
TIMER_POP();
|
||||
}
|
||||
|
||||
void PathfinderMob::checkHurtTarget( Entity* target, float d )
|
||||
{
|
||||
}
|
||||
|
||||
void PathfinderMob::checkCantSeeTarget( Entity* target, float d )
|
||||
{
|
||||
if (d > 32)
|
||||
attackTargetId = 0;
|
||||
}
|
||||
|
||||
float PathfinderMob::getWalkTargetValue( int x, int y, int z )
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
Entity* PathfinderMob::findAttackTarget()
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
float PathfinderMob::getWalkingSpeedModifier() {
|
||||
float speed = super::getWalkingSpeedModifier();
|
||||
if (fleeTime > 0) speed *= 2;
|
||||
return speed;
|
||||
}
|
||||
|
||||
int PathfinderMob::getNoActionTime() {
|
||||
return noActionTime;
|
||||
}
|
||||
|
||||
PathNavigation* PathfinderMob::getNavigation() {
|
||||
return navigation;
|
||||
}
|
||||
Reference in New Issue
Block a user