the game where you go into mines and start crafting! but for consoles (forked directly from smartcmd's github)
at main 599 lines 14 kB view raw
1#include "stdafx.h" 2#include "com.mojang.nbt.h" 3#include "net.minecraft.world.level.tile.h" 4#include "net.minecraft.world.phys.h" 5#include "net.minecraft.world.level.h" 6#include "net.minecraft.world.item.h" 7#include "net.minecraft.world.entity.h" 8#include "net.minecraft.world.entity.animal.h" 9#include "net.minecraft.world.entity.ai.attributes.h" 10#include "net.minecraft.world.entity.ai.goal.h" 11#include "net.minecraft.world.entity.ai.goal.target.h" 12#include "net.minecraft.world.entity.ai.navigation.h" 13#include "net.minecraft.world.entity.monster.h" 14#include "net.minecraft.world.entity.player.h" 15#include "net.minecraft.world.entity.projectile.h" 16#include "net.minecraft.world.level.pathfinder.h" 17#include "net.minecraft.world.damagesource.h" 18#include "net.minecraft.stats.h" 19#include "Sheep.h" 20#include "Wolf.h" 21#include "..\Minecraft.Client\Textures.h" 22#include "SoundTypes.h" 23 24 25 26Wolf::Wolf(Level *level) : TamableAnimal( level ) 27{ 28 // 4J Stu - This function call had to be moved here from the Entity ctor to ensure that 29 // the derived version of the function is called 30 this->defineSynchedData(); 31 registerAttributes(); 32 setHealth(getMaxHealth()); 33 34 interestedAngle = interestedAngleO = 0.0f; 35 m_isWet = isShaking = false; 36 shakeAnim = shakeAnimO = 0.0f; 37 38 this->setSize(0.60f, 0.8f); 39 40 getNavigation()->setAvoidWater(true); 41 goalSelector.addGoal(1, new FloatGoal(this)); 42 goalSelector.addGoal(2, sitGoal, false); 43 goalSelector.addGoal(3, new LeapAtTargetGoal(this, 0.4)); 44 goalSelector.addGoal(4, new MeleeAttackGoal(this, 1.0, true)); 45 goalSelector.addGoal(5, new FollowOwnerGoal(this, 1.0, 10, 2)); 46 goalSelector.addGoal(6, new BreedGoal(this, 1.0)); 47 goalSelector.addGoal(7, new RandomStrollGoal(this, 1.0)); 48 goalSelector.addGoal(8, new BegGoal(this, 8)); 49 goalSelector.addGoal(9, new LookAtPlayerGoal(this, typeid(Player), 8)); 50 goalSelector.addGoal(9, new RandomLookAroundGoal(this)); 51 52 targetSelector.addGoal(1, new OwnerHurtByTargetGoal(this)); 53 targetSelector.addGoal(2, new OwnerHurtTargetGoal(this)); 54 targetSelector.addGoal(3, new HurtByTargetGoal(this, true)); 55 targetSelector.addGoal(4, new NonTameRandomTargetGoal(this, typeid(Sheep), 200, false)); 56 57 setTame(false); // Initialize health 58} 59 60void Wolf::registerAttributes() 61{ 62 TamableAnimal::registerAttributes(); 63 64 getAttribute(SharedMonsterAttributes::MOVEMENT_SPEED)->setBaseValue(0.3f); 65 66 if (isTame()) 67 { 68 getAttribute(SharedMonsterAttributes::MAX_HEALTH)->setBaseValue(TAME_HEALTH); 69 } 70 else 71 { 72 getAttribute(SharedMonsterAttributes::MAX_HEALTH)->setBaseValue(START_HEALTH); 73 } 74} 75 76bool Wolf::useNewAi() 77{ 78 return true; 79} 80 81void Wolf::setTarget(shared_ptr<LivingEntity> target) 82{ 83 TamableAnimal::setTarget(target); 84 if ( target == NULL ) 85 { 86 setAngry(false); 87 } 88 else if(!isTame()) 89 { 90 setAngry(true); 91 } 92} 93 94void Wolf::serverAiMobStep() 95{ 96 entityData->set(DATA_HEALTH_ID, getHealth()); 97} 98 99void Wolf::defineSynchedData() 100{ 101 TamableAnimal::defineSynchedData(); 102 entityData->define(DATA_HEALTH_ID, getHealth()); 103 entityData->define(DATA_INTERESTED_ID, (byte)0); 104 entityData->define(DATA_COLLAR_COLOR, (byte) ColoredTile::getTileDataForItemAuxValue(DyePowderItem::RED)); 105} 106 107void Wolf::playStepSound(int xt, int yt, int zt, int t) 108{ 109 playSound(eSoundType_MOB_WOLF_STEP, 0.15f, 1); 110} 111 112void Wolf::addAdditonalSaveData(CompoundTag *tag) 113{ 114 TamableAnimal::addAdditonalSaveData(tag); 115 116 tag->putBoolean(L"Angry", isAngry()); 117 tag->putByte(L"CollarColor", (byte) getCollarColor()); 118} 119 120void Wolf::readAdditionalSaveData(CompoundTag *tag) 121{ 122 TamableAnimal::readAdditionalSaveData(tag); 123 124 setAngry(tag->getBoolean(L"Angry")); 125 if (tag->contains(L"CollarColor")) setCollarColor(tag->getByte(L"CollarColor")); 126} 127 128int Wolf::getAmbientSound() 129{ 130 if (isAngry()) 131 { 132 return eSoundType_MOB_WOLF_GROWL; 133 } 134 if (random->nextInt(3) == 0) 135 { 136 if (isTame() && entityData->getFloat(DATA_HEALTH_ID) < 10) 137 { 138 return eSoundType_MOB_WOLF_WHINE; 139 } 140 return eSoundType_MOB_WOLF_PANTING; 141 } 142 return eSoundType_MOB_WOLF_BARK; 143} 144 145int Wolf::getHurtSound() 146{ 147 return eSoundType_MOB_WOLF_HURT; 148} 149 150int Wolf::getDeathSound() 151{ 152 return eSoundType_MOB_WOLF_DEATH; 153} 154 155float Wolf::getSoundVolume() 156{ 157 return 0.4f; 158} 159 160int Wolf::getDeathLoot() 161{ 162 return -1; 163} 164 165void Wolf::aiStep() 166{ 167 TamableAnimal::aiStep(); 168 169 if (!level->isClientSide && m_isWet && !isShaking && !isPathFinding() && onGround) 170 { 171 isShaking = true; 172 shakeAnim = 0; 173 shakeAnimO = 0; 174 175 level->broadcastEntityEvent(shared_from_this(), EntityEvent::SHAKE_WETNESS); 176 } 177} 178 179void Wolf::tick() 180{ 181 TamableAnimal::tick(); 182 183 interestedAngleO = interestedAngle; 184 if (isInterested()) 185 { 186 interestedAngle = interestedAngle + (1 - interestedAngle) * 0.4f; 187 } 188 else 189 { 190 interestedAngle = interestedAngle + (0 - interestedAngle) * 0.4f; 191 } 192 if (isInterested()) 193 { 194 lookTime = 10; 195 } 196 197 if (isInWaterOrRain()) 198 { 199 m_isWet = true; 200 isShaking = false; 201 shakeAnim = 0; 202 shakeAnimO = 0; 203 } 204 else if (m_isWet || isShaking) 205 { 206 if (isShaking) 207 { 208 209 if (shakeAnim == 0) 210 { 211 playSound(eSoundType_MOB_WOLF_SHAKE, getSoundVolume(), (random->nextFloat() - random->nextFloat()) * 0.2f + 1.0f); 212 } 213 214 shakeAnimO = shakeAnim; 215 shakeAnim += 0.05f; 216 217 if (shakeAnimO >= 2) 218 { 219 m_isWet = false; 220 isShaking = false; 221 shakeAnimO = 0; 222 shakeAnim = 0; 223 } 224 225 if (shakeAnim > 0.4f) 226 { 227 float yt = (float) bb->y0; 228 int shakeCount = (int) (Mth::sin((shakeAnim - 0.4f) * PI) * 7.0f); 229 for (int i = 0; i < shakeCount; i++) 230 { 231 float xo = (random->nextFloat() * 2 - 1) * bbWidth * 0.5f; 232 float zo = (random->nextFloat() * 2 - 1) * bbWidth * 0.5f; 233 level->addParticle(eParticleType_splash, x + xo, yt + 0.8f, z + zo, xd, yd, zd); 234 } 235 } 236 } 237 } 238} 239 240bool Wolf::isWet() 241{ 242 return m_isWet; 243} 244 245float Wolf::getWetShade(float a) 246{ 247 return 0.75f + ((shakeAnimO + (shakeAnim - shakeAnimO) * a) / 2.0f) * 0.25f; 248} 249 250float Wolf::getBodyRollAngle(float a, float offset) 251{ 252 float progress = ((shakeAnimO + (shakeAnim - shakeAnimO) * a) + offset) / 1.8f; 253 if (progress < 0) 254 { 255 progress = 0; 256 } 257 else if (progress > 1) 258 { 259 progress = 1; 260 } 261 return Mth::sin(progress * PI) * Mth::sin(progress * PI * 11.0f) * 0.15f * PI; 262} 263 264float Wolf::getHeadRollAngle(float a) 265{ 266 return (interestedAngleO + (interestedAngle - interestedAngleO) * a) * 0.15f * PI; 267} 268 269float Wolf::getHeadHeight() 270{ 271 return bbHeight * 0.8f; 272} 273 274int Wolf::getMaxHeadXRot() 275{ 276 if (isSitting()) 277 { 278 return 20; 279 } 280 return TamableAnimal::getMaxHeadXRot(); 281} 282 283bool Wolf::hurt(DamageSource *source, float dmg) 284{ 285 // 4J: Protect owned wolves from untrusted players 286 if (isTame()) 287 { 288 shared_ptr<Entity> entity = source->getDirectEntity(); 289 if (entity != NULL && entity->instanceof(eTYPE_PLAYER)) 290 { 291 shared_ptr<Player> attacker = dynamic_pointer_cast<Player>(entity); 292 attacker->canHarmPlayer(getOwnerUUID()); 293 } 294 } 295 296 if (isInvulnerable()) return false; 297 shared_ptr<Entity> sourceEntity = source->getEntity(); 298 sitGoal->wantToSit(false); 299 if (sourceEntity != NULL && !(sourceEntity->instanceof(eTYPE_PLAYER) || sourceEntity->instanceof(eTYPE_ARROW))) 300 { 301 // Take half damage from non-players and arrows 302 dmg = (dmg + 1) / 2; 303 } 304 return TamableAnimal::hurt(source, dmg); 305} 306 307bool Wolf::doHurtTarget(shared_ptr<Entity> target) 308{ 309 int damage = isTame() ? 4 : 2; 310 return target->hurt(DamageSource::mobAttack(dynamic_pointer_cast<Mob>(shared_from_this())), damage); 311} 312 313void Wolf::setTame(bool value) 314{ 315 TamableAnimal::setTame(value); 316 317 if (value) 318 { 319 getAttribute(SharedMonsterAttributes::MAX_HEALTH)->setBaseValue(TAME_HEALTH); 320 } 321 else 322 { 323 getAttribute(SharedMonsterAttributes::MAX_HEALTH)->setBaseValue(START_HEALTH); 324 } 325} 326 327void Wolf::tame(const wstring &wsOwnerUUID, bool bDisplayTamingParticles, bool bSetSitting) 328{ 329 setTame(true); 330 setPath(NULL); 331 setTarget(nullptr); 332 sitGoal->wantToSit(bSetSitting); 333 setHealth(TAME_HEALTH); 334 335 setOwnerUUID(wsOwnerUUID); 336 337 // We'll not show the taming particles if this is a baby wolf 338 spawnTamingParticles(bDisplayTamingParticles); 339} 340 341bool Wolf::mobInteract(shared_ptr<Player> player) 342{ 343 shared_ptr<ItemInstance> item = player->inventory->getSelected(); 344 345 if (isTame()) 346 { 347 if (item != NULL) 348 { 349 if(dynamic_cast<FoodItem *>(Item::items[item->id]) != NULL) 350 { 351 FoodItem *food = dynamic_cast<FoodItem *>( Item::items[item->id] ); 352 353 if (food->isMeat() && entityData->getFloat(DATA_HEALTH_ID) < MAX_HEALTH) 354 { 355 heal(food->getNutrition()); 356 // 4J-PB - don't lose the bone in creative mode 357 if (player->abilities.instabuild==false) 358 { 359 item->count--; 360 if (item->count <= 0) 361 { 362 player->inventory->setItem(player->inventory->selected, nullptr); 363 } 364 } 365 return true; 366 } 367 } 368 else if (item->id == Item::dye_powder_Id) 369 { 370 int color = ColoredTile::getTileDataForItemAuxValue(item->getAuxValue()); 371 if (color != getCollarColor()) 372 { 373 setCollarColor(color); 374 375 if (!player->abilities.instabuild && --item->count <= 0) 376 { 377 player->inventory->setItem(player->inventory->selected, nullptr); 378 } 379 380 return true; 381 } 382 } 383 } 384 if (equalsIgnoreCase(player->getUUID(), getOwnerUUID())) 385 { 386 if (!level->isClientSide && !isFood(item)) 387 { 388 sitGoal->wantToSit(!isSitting()); 389 jumping = false; 390 setPath(NULL); 391 setAttackTarget(nullptr); 392 setTarget(nullptr); 393 } 394 } 395 } 396 else 397 { 398 if (item != NULL && item->id == Item::bone->id && !isAngry()) 399 { 400 // 4J-PB - don't lose the bone in creative mode 401 if (player->abilities.instabuild==false) 402 { 403 item->count--; 404 if (item->count <= 0) 405 { 406 player->inventory->setItem(player->inventory->selected, nullptr); 407 } 408 } 409 410 if (!level->isClientSide) 411 { 412 if (random->nextInt(3) == 0) 413 { 414 // 4J : WESTY: Added for new acheivements. 415 player->awardStat(GenericStats::tamedEntity(eTYPE_WOLF),GenericStats::param_tamedEntity(eTYPE_WOLF)); 416 417 // 4J Changed to this 418 tame(player->getUUID(),true,true); 419 420 level->broadcastEntityEvent(shared_from_this(), EntityEvent::TAMING_SUCCEEDED); 421 } 422 else 423 { 424 spawnTamingParticles(false); 425 level->broadcastEntityEvent(shared_from_this(), EntityEvent::TAMING_FAILED); 426 } 427 } 428 429 return true; 430 } 431 432 // 4J-PB - stop wild wolves going in to Love Mode (even though they do on Java, but don't breed) 433 if((item != NULL) && isFood(item)) 434 { 435 return false; 436 } 437 } 438 return TamableAnimal::mobInteract(player); 439} 440 441void Wolf::handleEntityEvent(byte id) 442{ 443 if (id == EntityEvent::SHAKE_WETNESS) 444 { 445 isShaking = true; 446 shakeAnim = 0; 447 shakeAnimO = 0; 448 } 449 else 450 { 451 TamableAnimal::handleEntityEvent(id); 452 } 453} 454 455float Wolf::getTailAngle() 456{ 457 if (isAngry()) 458 { 459 return 0.49f * PI; 460 } 461 else if (isTame()) 462 { 463 return (0.55f - (MAX_HEALTH - entityData->getFloat(DATA_HEALTH_ID)) * 0.02f) * PI; 464 } 465 return 0.20f * PI; 466} 467 468bool Wolf::isFood(shared_ptr<ItemInstance> item) 469{ 470 if (item == NULL) return false; 471 if (dynamic_cast<FoodItem *>(Item::items[item->id]) == NULL) return false; 472 return ((FoodItem *) Item::items[item->id])->isMeat(); 473} 474 475int Wolf::getMaxSpawnClusterSize() 476{ 477 // 4J - changed - was 8 but we have a limit of only 8 wolves in the world so doesn't seem right potentially spawning them all in once cluster 478 return 4; 479} 480 481bool Wolf::isAngry() 482{ 483 return (entityData->getByte(DATA_FLAGS_ID) & 0x02) != 0; 484} 485 486void Wolf::setAngry(bool value) 487{ 488 byte current = entityData->getByte(DATA_FLAGS_ID); 489 if (value) 490 { 491 entityData->set(DATA_FLAGS_ID, (byte) (current | 0x02)); 492 } 493 else 494 { 495 entityData->set(DATA_FLAGS_ID, (byte) (current & ~0x02)); 496 } 497} 498 499int Wolf::getCollarColor() 500{ 501 return entityData->getByte(DATA_COLLAR_COLOR) & 0xF; 502} 503 504void Wolf::setCollarColor(int color) 505{ 506 entityData->set(DATA_COLLAR_COLOR, (byte) (color & 0xF)); 507} 508 509// 4J-PB added for tooltips 510int Wolf::GetSynchedHealth() 511{ 512 return getEntityData()->getInteger(DATA_HEALTH_ID); 513} 514 515shared_ptr<AgableMob> Wolf::getBreedOffspring(shared_ptr<AgableMob> target) 516{ 517 // 4J - added limit to wolves that can be bred 518 if( level->canCreateMore( GetType(), Level::eSpawnType_Breed) ) 519 { 520 shared_ptr<Wolf> pBabyWolf = shared_ptr<Wolf>( new Wolf(level) ); 521 522 if(!getOwnerUUID().empty()) 523 { 524 // set the baby wolf to be tame, and assign the owner 525 pBabyWolf->tame(getOwnerUUID(),false,false); 526 } 527 return pBabyWolf; 528 } 529 else 530 { 531 return nullptr; 532 } 533} 534 535void Wolf::setIsInterested(bool value) 536{ 537 if (value) 538 { 539 entityData->set(DATA_INTERESTED_ID, (byte) 1); 540 } 541 else 542 { 543 entityData->set(DATA_INTERESTED_ID, (byte) 0); 544 } 545} 546 547bool Wolf::canMate(shared_ptr<Animal> animal) 548{ 549 if (animal == shared_from_this()) return false; 550 if (!isTame()) return false; 551 552 if (!animal->instanceof(eTYPE_WOLF)) return false; 553 shared_ptr<Wolf> partner = dynamic_pointer_cast<Wolf>(animal); 554 555 if (partner == NULL) return false; 556 if (!partner->isTame()) return false; 557 if (partner->isSitting()) return false; 558 559 return isInLove() && partner->isInLove(); 560} 561 562bool Wolf::isInterested() 563{ 564 return entityData->getByte(DATA_INTERESTED_ID) == 1; 565} 566 567bool Wolf::removeWhenFarAway() 568{ 569 return !isTame() && tickCount > SharedConstants::TICKS_PER_SECOND * 60 * 2; 570} 571 572bool Wolf::wantsToAttack(shared_ptr<LivingEntity> target, shared_ptr<LivingEntity> owner) 573{ 574 // filter un-attackable mobs 575 if (target->GetType() == eTYPE_CREEPER || target->GetType() == eTYPE_GHAST) 576 { 577 return false; 578 } 579 // never target wolves that has this player as owner 580 if (target->GetType() == eTYPE_WOLF) 581 { 582 shared_ptr<Wolf> wolfTarget = dynamic_pointer_cast<Wolf>(target); 583 if (wolfTarget->isTame() && wolfTarget->getOwner() == owner) 584 { 585 return false; 586 } 587 } 588 if ( target->instanceof(eTYPE_PLAYER) && owner->instanceof(eTYPE_PLAYER) && !dynamic_pointer_cast<Player>(owner)->canHarmPlayer(dynamic_pointer_cast<Player>(target) )) 589 { 590 // pvp is off 591 return false; 592 } 593 // don't attack tame horses 594 if ((target->GetType() == eTYPE_HORSE) && dynamic_pointer_cast<EntityHorse>(target)->isTamed()) 595 { 596 return false; 597 } 598 return true; 599}