the game where you go into mines and start crafting! but for consoles (forked directly from smartcmd's github)
at main 379 lines 10 kB view raw
1#include "stdafx.h" 2#include "net.minecraft.world.entity.h" 3#include "net.minecraft.world.entity.animal.h" 4#include "net.minecraft.world.entity.ai.attributes.h" 5#include "net.minecraft.world.entity.ai.goal.h" 6#include "net.minecraft.world.entity.ai.navigation.h" 7#include "net.minecraft.world.entity.monster.h" 8#include "net.minecraft.world.level.h" 9#include "net.minecraft.world.level.pathfinder.h" 10#include "net.minecraft.world.phys.h" 11#include "SharedConstants.h" 12#include "PathfinderMob.h" 13 14AttributeModifier *PathfinderMob::SPEED_MODIFIER_FLEEING = (new AttributeModifier(eModifierId_MOB_FLEEING, 2.0f, AttributeModifier::OPERATION_MULTIPLY_TOTAL))->setSerialize(false); 15 16PathfinderMob::PathfinderMob(Level *level) : Mob( level ) 17{ 18 path = NULL; 19 attackTarget = nullptr; 20 holdGround = false; 21 fleeTime = 0; 22 23 restrictRadius = -1; 24 restrictCenter = new Pos(0, 0, 0); 25 addedLeashRestrictionGoal = false; 26 leashRestrictionGoal = new MoveTowardsRestrictionGoal(this, 1.0f); 27} 28 29bool PathfinderMob::shouldHoldGround() 30{ 31 return false; 32} 33 34PathfinderMob::~PathfinderMob() 35{ 36 delete path; 37 delete restrictCenter; 38 delete leashRestrictionGoal; 39} 40 41void PathfinderMob::serverAiStep() 42{ 43 if (fleeTime > 0) 44 { 45 if (--fleeTime == 0) 46 { 47 AttributeInstance *speed = getAttribute(SharedMonsterAttributes::MOVEMENT_SPEED); 48 speed->removeModifier(SPEED_MODIFIER_FLEEING); 49 } 50 } 51 holdGround = shouldHoldGround(); 52 float maxDist = 16; 53 54 if (attackTarget == NULL) 55 { 56 attackTarget = findAttackTarget(); 57 if (attackTarget != NULL) 58 { 59 setPath(level->findPath(shared_from_this(), attackTarget, maxDist, true, false, false, true)); // 4J - changed to setPath from path = 60 } 61 } 62 else 63 { 64 if (attackTarget->isAlive()) 65 { 66 float d = attackTarget->distanceTo(shared_from_this()); 67 if (canSee(attackTarget)) 68 { 69 checkHurtTarget(attackTarget, d); 70 } 71 } 72 else 73 { 74 attackTarget = nullptr; 75 } 76 } 77 78 /* 79 * if (holdGround) { xxa = 0; yya = 0; jumping = false; return; } 80 */ 81 82 // 4J - a few changes here so that we can call findRandomStrollLocation for a sub-set of things that it normally wouldn't be in the java game. 83 // This is so that we can have entities wander around a little, in order that we can measure how far they wander and then determine (if they wander too far) that 84 // they aren't enclosed. We don't want the extra network overhead of just having Everything wandering round all the time, so have put a management system in place 85 // that selects a subset of entities which have had their flag set through the considerForExtraWandering method so that these can keep doing random strolling. 86 87 if (!holdGround && (attackTarget != NULL && (path == NULL || random->nextInt(20) == 0))) 88 { 89 setPath(level->findPath(shared_from_this(), attackTarget, maxDist, true, false, false, true));// 4J - changed to setPath from path = 90 } 91 else if (!holdGround && ((path == NULL && (random->nextInt(180) == 0) || fleeTime > 0) || (random->nextInt(120) == 0 || fleeTime > 0))) 92 { 93 if(noActionTime < SharedConstants::TICKS_PER_SECOND * 5) 94 { 95 findRandomStrollLocation(); 96 } 97 } 98 else if (!holdGround && (path == NULL ) ) 99 { 100 if( ( noActionTime >= SharedConstants::TICKS_PER_SECOND * 5 ) && isExtraWanderingEnabled() ) 101 { 102 // This entity wouldn't normally be randomly strolling. However, if our management system says that it should do, then do. Don't 103 // bother waiting for random conditions to be met before picking a direction though as the point here is to see if it is possible to 104 // stroll out of a given area and so waiting around is just wasting time 105 findRandomStrollLocation(getWanderingQuadrant()); 106 } 107 } 108 109 // Consider this for extra strolling if it is protected against despawning. We aren't interested in ones that aren't protected as the whole point of this 110 // extra wandering is to potentially transition from protected to not protected. 111 considerForExtraWandering( isDespawnProtected() ); 112 113 int yFloor = Mth::floor(bb->y0 + 0.5f); 114 115 bool inWater = isInWater(); 116 bool inLava = isInLava(); 117 xRot = 0; 118 if (path == NULL || random->nextInt(100) == 0) 119 { 120 this->Mob::serverAiStep(); 121 setPath(NULL);// 4J - changed to setPath from path = 122 return; 123 } 124 125 Vec3 *target = path->currentPos(shared_from_this()); 126 double r = bbWidth * 2; 127 while (target != NULL && target->distanceToSqr(x, target->y, z) < r * r) 128 { 129 path->next(); 130 if (path->isDone()) 131 { 132 target = NULL; 133 setPath(NULL); // 4J - changed to setPath from path = 134 } 135 else target = path->currentPos(shared_from_this()); 136 } 137 138 jumping = false; 139 if (target != NULL) 140 { 141 double xd = target->x - x; 142 double zd = target->z - z; 143 double yd = target->y - yFloor; 144 float yRotD = (float) (atan2(zd, xd) * 180 / PI) - 90; 145 float rotDiff = Mth::wrapDegrees(yRotD - yRot); 146 yya = (float) getAttribute(SharedMonsterAttributes::MOVEMENT_SPEED)->getValue(); 147 if (rotDiff > MAX_TURN) 148 { 149 rotDiff = MAX_TURN; 150 } 151 if (rotDiff < -MAX_TURN) 152 { 153 rotDiff = -MAX_TURN; 154 } 155 yRot += rotDiff; 156 157 if (holdGround) 158 { 159 if (attackTarget != NULL) 160 { 161 double xd2 = attackTarget->x - x; 162 double zd2 = attackTarget->z - z; 163 164 float oldyRot = yRot; 165 yRot = (float) (atan2(zd2, xd2) * 180 / PI) - 90; 166 167 rotDiff = ((oldyRot - yRot) + 90) * PI / 180; 168 xxa = -Mth::sin(rotDiff) * yya * 1.0f; 169 yya = Mth::cos(rotDiff) * yya * 1.0f; 170 } 171 } 172 if (yd > 0) 173 { 174 jumping = true; 175 } 176 } 177 178 if (attackTarget != NULL) 179 { 180 lookAt(attackTarget, 30, 30); 181 } 182 183 if (horizontalCollision && !isPathFinding()) jumping = true; 184 if (random->nextFloat() < 0.8f && (inWater || inLava)) jumping = true; 185} 186 187void PathfinderMob::findRandomStrollLocation(int quadrant/*=-1*/) // 4J - added quadrant 188{ 189 bool hasBest = false; 190 int xBest = -1; 191 int yBest = -1; 192 int zBest = -1; 193 float best = -99999; 194 for (int i = 0; i < 10; i++) 195 { 196 // 4J - added quadrant parameter to this method so that the caller can request that only stroll locations in one quadrant be found. If -1 is passed then 197 // behaviour is the same as the java game 198 int xt, zt; 199 int yt = Mth::floor(y + random->nextInt(7) - 3); 200 if( quadrant == -1 ) 201 { 202 xt = Mth::floor(x + random->nextInt(13) - 6); 203 zt = Mth::floor(z + random->nextInt(13) - 6); 204 } 205 else 206 { 207 int sx = ( ( quadrant & 1 ) ? -1 : 1 ); 208 int sz = ( ( quadrant & 2 ) ? -1 : 1 ); 209 xt = Mth::floor(x + random->nextInt(7) * sx); 210 zt = Mth::floor(z + random->nextInt(7) * sz); 211 } 212 float value = getWalkTargetValue(xt, yt, zt); 213 if (value > best) 214 { 215 best = value; 216 xBest = xt; 217 yBest = yt; 218 zBest = zt; 219 hasBest = true; 220 } 221 } 222 if (hasBest) 223 { 224 setPath(level->findPath(shared_from_this(), xBest, yBest, zBest, 10, true, false, false, true)); // 4J - changed to setPath from path = 225 } 226} 227 228void PathfinderMob::checkHurtTarget(shared_ptr<Entity> target, float d) 229{ 230} 231 232float PathfinderMob::getWalkTargetValue(int x, int y, int z) 233{ 234 return 0; 235} 236 237shared_ptr<Entity> PathfinderMob::findAttackTarget() 238{ 239 return shared_ptr<Entity>(); 240} 241 242 243bool PathfinderMob::canSpawn() 244{ 245 int xt = Mth::floor(x); 246 int yt = Mth::floor(bb->y0); 247 int zt = Mth::floor(z); 248 return this->Mob::canSpawn() && getWalkTargetValue(xt, yt, zt) >= 0; 249} 250 251bool PathfinderMob::isPathFinding() 252{ 253 return path != NULL; 254} 255 256void PathfinderMob::setPath(Path *path) 257{ 258 delete this->path; 259 this->path = path; 260} 261 262shared_ptr<Entity> PathfinderMob::getAttackTarget() 263{ 264 return attackTarget; 265} 266 267void PathfinderMob::setAttackTarget(shared_ptr<Entity> attacker) 268{ 269 attackTarget = attacker; 270} 271 272// might move to navigation, might make area 273bool PathfinderMob::isWithinRestriction() 274{ 275 return isWithinRestriction(Mth::floor(x), Mth::floor(y), Mth::floor(z)); 276} 277 278bool PathfinderMob::isWithinRestriction(int x, int y, int z) 279{ 280 if (restrictRadius == -1) return true; 281 return restrictCenter->distSqr(x, y, z) < restrictRadius * restrictRadius; 282} 283 284void PathfinderMob::restrictTo(int x, int y, int z, int radius) 285{ 286 restrictCenter->set(x, y, z); 287 restrictRadius = radius; 288} 289 290Pos *PathfinderMob::getRestrictCenter() 291{ 292 return restrictCenter; 293} 294 295float PathfinderMob::getRestrictRadius() 296{ 297 return restrictRadius; 298} 299 300void PathfinderMob::clearRestriction() 301{ 302 restrictRadius = -1; 303} 304 305bool PathfinderMob::hasRestriction() 306{ 307 return restrictRadius != -1; 308} 309 310void PathfinderMob::tickLeash() 311{ 312 Mob::tickLeash(); 313 314 if (isLeashed() && getLeashHolder() != NULL && getLeashHolder()->level == this->level) 315 { 316 // soft restriction 317 shared_ptr<Entity> leashHolder = getLeashHolder(); 318 restrictTo((int) leashHolder->x, (int) leashHolder->y, (int) leashHolder->z, 5); 319 320 float _distanceTo = distanceTo(leashHolder); 321 322 shared_ptr<TamableAnimal> tamabaleAnimal = shared_from_this()->instanceof(eTYPE_TAMABLE_ANIMAL) ? dynamic_pointer_cast<TamableAnimal>(shared_from_this()) : nullptr; 323 if ( (tamabaleAnimal != NULL) && tamabaleAnimal->isSitting() ) 324 { 325 if (_distanceTo > 10) 326 { 327 dropLeash(true, true); 328 } 329 return; 330 } 331 332 if (!addedLeashRestrictionGoal) 333 { 334 goalSelector.addGoal(2, leashRestrictionGoal, false); 335 getNavigation()->setAvoidWater(false); 336 addedLeashRestrictionGoal = true; 337 } 338 339 onLeashDistance(_distanceTo); 340 341 if (_distanceTo > 4) 342 { 343 // harder restriction 344 getNavigation()->moveTo(leashHolder, 1.0); 345 } 346 if (_distanceTo > 6) 347 { 348 // hardest restriction 349 double dx = (leashHolder->x - x) / _distanceTo; 350 double dy = (leashHolder->y - y) / _distanceTo; 351 double dz = (leashHolder->z - z) / _distanceTo; 352 353 xd += dx * abs(dx) * .4; 354 yd += dy * abs(dy) * .4; 355 zd += dz * abs(dz) * .4; 356 } 357 if (_distanceTo > 10) 358 { 359 dropLeash(true, true); 360 } 361 362 } 363 else if (!isLeashed() && addedLeashRestrictionGoal) 364 { 365 addedLeashRestrictionGoal = false; 366 goalSelector.removeGoal(leashRestrictionGoal); 367 getNavigation()->setAvoidWater(true); 368 clearRestriction(); 369 } 370} 371 372void PathfinderMob::onLeashDistance(float distanceToLeashHolder) 373{ 374} 375 376bool PathfinderMob::couldWander() 377{ 378 return (noActionTime < SharedConstants::TICKS_PER_SECOND * 5) || ( isExtraWanderingEnabled() ); 379}