the game where you go into mines and start crafting! but for consoles (forked directly from smartcmd's github)
at main 439 lines 11 kB view raw
1#include "stdafx.h" 2#include "net.minecraft.world.entity.player.h" 3#include "net.minecraft.world.entity.h" 4#include "net.minecraft.world.entity.ai.attributes.h" 5#include "net.minecraft.world.entity.monster.h" 6#include "net.minecraft.world.item.h" 7#include "net.minecraft.world.level.h" 8#include "net.minecraft.world.level.tile.h" 9#include "net.minecraft.world.damagesource.h" 10#include "net.minecraft.world.phys.h" 11#include "com.mojang.nbt.h" 12#include "..\Minecraft.Client\Textures.h" 13#include "EnderMan.h" 14 15AttributeModifier *EnderMan::SPEED_MODIFIER_ATTACKING = (new AttributeModifier(eModifierId_MOB_ENDERMAN_ATTACKSPEED, 6.2f, AttributeModifier::OPERATION_ADDITION))->setSerialize(false); 16 17bool EnderMan::MAY_TAKE[256]; 18 19void EnderMan::staticCtor() 20{ 21 ZeroMemory(MAY_TAKE, sizeof(bool) * 256); 22 MAY_TAKE[Tile::grass_Id] = true; 23 MAY_TAKE[Tile::dirt_Id] = true; 24 MAY_TAKE[Tile::sand_Id] = true; 25 MAY_TAKE[Tile::gravel_Id] = true; 26 MAY_TAKE[Tile::flower_Id] = true; 27 MAY_TAKE[Tile::rose_Id] = true; 28 MAY_TAKE[Tile::mushroom_brown_Id] = true; 29 MAY_TAKE[Tile::mushroom_red_Id] = true; 30 MAY_TAKE[Tile::tnt_Id] = true; 31 MAY_TAKE[Tile::cactus_Id] = true; 32 MAY_TAKE[Tile::clay_Id] = true; 33 MAY_TAKE[Tile::pumpkin_Id] = true; 34 MAY_TAKE[Tile::melon_Id] = true; 35 MAY_TAKE[Tile::mycel_Id] = true; 36} 37 38EnderMan::EnderMan(Level *level) : Monster( level ) 39{ 40 // 4J Stu - This function call had to be moved here from the Entity ctor to ensure that 41 // the derived version of the function is called 42 // Brought forward from 1.2.3 43 this->defineSynchedData(); 44 registerAttributes(); 45 setHealth(getMaxHealth()); 46 47 // 4J initialisors 48 teleportTime = 0; 49 aggroTime = 0; 50 lastAttackTarget = nullptr; 51 aggroedByPlayer = false; 52 53 setSize(0.6f, 2.9f); 54 footSize = 1; 55} 56 57void EnderMan::registerAttributes() 58{ 59 Monster::registerAttributes(); 60 61 getAttribute(SharedMonsterAttributes::MAX_HEALTH)->setBaseValue(40); 62 getAttribute(SharedMonsterAttributes::MOVEMENT_SPEED)->setBaseValue(0.3f); 63 getAttribute(SharedMonsterAttributes::ATTACK_DAMAGE)->setBaseValue(7); 64} 65 66void EnderMan::defineSynchedData() 67{ 68 Monster::defineSynchedData(); 69 70 entityData->define(DATA_CARRY_ITEM_ID, (byte) 0); 71 entityData->define(DATA_CARRY_ITEM_DATA, (byte) 0); 72 entityData->define(DATA_CREEPY, (byte) 0); 73} 74 75void EnderMan::addAdditonalSaveData(CompoundTag *tag) 76{ 77 Monster::addAdditonalSaveData(tag); 78 tag->putShort(L"carried", (short) getCarryingTile()); 79 tag->putShort(L"carriedData", (short) getCarryingData()); 80} 81 82void EnderMan::readAdditionalSaveData(CompoundTag *tag) 83{ 84 Monster::readAdditionalSaveData(tag); 85 setCarryingTile(tag->getShort(L"carried")); 86 setCarryingData(tag->getShort(L"carryingData")); 87} 88 89shared_ptr<Entity> EnderMan::findAttackTarget() 90{ 91#ifndef _FINAL_BUILD 92 if(app.GetMobsDontAttackEnabled()) 93 { 94 return shared_ptr<Player>(); 95 } 96#endif 97 98 shared_ptr<Player> player = level->getNearestAttackablePlayer(shared_from_this(), 64); 99 if (player != NULL) 100 { 101 if (isLookingAtMe(player)) 102 { 103 aggroedByPlayer = true; 104 if (aggroTime == 0) level->playEntitySound(player, eSoundType_MOB_ENDERMAN_STARE, 1, 1); 105 if (aggroTime++ == 5) 106 { 107 aggroTime = 0; 108 setCreepy(true); 109 return player; 110 } 111 } 112 else 113 { 114 aggroTime = 0; 115 } 116 } 117 return nullptr; 118} 119 120bool EnderMan::isLookingAtMe(shared_ptr<Player> player) 121{ 122 shared_ptr<ItemInstance> helmet = player->inventory->armor[3]; 123 if (helmet != NULL && helmet->id == Tile::pumpkin_Id) return false; 124 125 Vec3 *look = player->getViewVector(1)->normalize(); 126 Vec3 *dir = Vec3::newTemp(x - player->x, (bb->y0 + bbHeight / 2) - (player->y + player->getHeadHeight()), z - player->z); 127 double dist = dir->length(); 128 dir = dir->normalize(); 129 double dot = look->dot(dir); 130 if (dot > 1 - 0.025 / dist) 131 { 132 return player->canSee(shared_from_this()); 133 } 134 return false; 135} 136 137void EnderMan::aiStep() 138{ 139 if (isInWaterOrRain()) hurt(DamageSource::drown, 1); 140 141 if (lastAttackTarget != attackTarget) 142 { 143 AttributeInstance *speed = getAttribute(SharedMonsterAttributes::MOVEMENT_SPEED); 144 speed->removeModifier(SPEED_MODIFIER_ATTACKING); 145 146 if (attackTarget != NULL) 147 { 148 speed->addModifier(new AttributeModifier(*SPEED_MODIFIER_ATTACKING)); 149 } 150 } 151 152 lastAttackTarget = attackTarget; 153 154 if (!level->isClientSide) 155 { 156 if (level->getGameRules()->getBoolean(GameRules::RULE_MOBGRIEFING)) 157 { 158 if (getCarryingTile() == 0) 159 { 160 if (random->nextInt(20) == 0) 161 { 162 int xt = Mth::floor(x - 2 + random->nextDouble() * 4); 163 int yt = Mth::floor(y + random->nextDouble() * 3); 164 int zt = Mth::floor(z - 2 + random->nextDouble() * 4); 165 int t = level->getTile(xt, yt, zt); 166 if(MAY_TAKE[t]) 167 { 168 setCarryingTile(level->getTile(xt, yt, zt)); 169 setCarryingData(level->getData(xt, yt, zt)); 170 level->setTileAndUpdate(xt, yt, zt, 0); 171 } 172 } 173 } 174 else 175 { 176 if (random->nextInt(2000) == 0) 177 { 178 int xt = Mth::floor(x - 1 + random->nextDouble() * 2); 179 int yt = Mth::floor(y + random->nextDouble() * 2); 180 int zt = Mth::floor(z - 1 + random->nextDouble() * 2); 181 int t = level->getTile(xt, yt, zt); 182 int bt = level->getTile(xt, yt - 1, zt); 183 if (t == 0 && bt > 0 && Tile::tiles[bt]->isCubeShaped()) 184 { 185 level->setTileAndData(xt, yt, zt, getCarryingTile(), getCarryingData(), Tile::UPDATE_ALL); 186 setCarryingTile(0); 187 } 188 } 189 } 190 } 191 } 192 193 194 for (int i = 0; i < 2; i++) 195 { 196 level->addParticle(eParticleType_ender, x + (random->nextDouble() - 0.5) * bbWidth, y + random->nextDouble() * bbHeight - 0.25f, z + (random->nextDouble() - 0.5) * bbWidth, 197 (random->nextDouble() - 0.5) * 2, -random->nextDouble(), (random->nextDouble() - 0.5) * 2); 198 } 199 200 if (level->isDay() && !level->isClientSide) 201 { 202 float br = getBrightness(1); 203 if (br > 0.5f) 204 { 205 if (level->canSeeSky(Mth::floor(x), (int)floor( y + 0.5 ), Mth::floor(z)) && random->nextFloat() * 30 < (br - 0.4f) * 2) 206 { 207 attackTarget = nullptr; 208 setCreepy(false); 209 aggroedByPlayer = false; 210 teleport(); 211 } 212 } 213 } 214 215 if (isInWaterOrRain() || isOnFire()) 216 { 217 attackTarget = nullptr; 218 setCreepy(false); 219 aggroedByPlayer = false; 220 teleport(); 221 } 222 223 if (isCreepy() && !aggroedByPlayer && random->nextInt(100) == 0) 224 { 225 setCreepy(false); 226 } 227 228 jumping = false; 229 if (attackTarget != NULL) 230 { 231 lookAt(attackTarget, 100, 100); 232 } 233 234 if (!level->isClientSide && isAlive()) 235 { 236 if (attackTarget != NULL) 237 { 238 if ( attackTarget->instanceof(eTYPE_PLAYER) && isLookingAtMe(dynamic_pointer_cast<Player>(attackTarget))) 239 { 240 if (attackTarget->distanceToSqr(shared_from_this()) < 4 * 4) 241 { 242 teleport(); 243 } 244 teleportTime = 0; 245 } 246 else if (attackTarget->distanceToSqr(shared_from_this()) > 16 * 16) 247 { 248 if (teleportTime++ >= 30) 249 { 250 if (teleportTowards(attackTarget)) 251 { 252 teleportTime = 0; 253 } 254 } 255 } 256 } 257 else 258 { 259 setCreepy(false); 260 teleportTime = 0; 261 } 262 } 263 264 Monster::aiStep(); 265} 266 267bool EnderMan::teleport() 268{ 269 double xx = x + (random->nextDouble() - 0.5) * 64; 270 double yy = y + (random->nextInt(64) - 32); 271 double zz = z + (random->nextDouble() - 0.5) * 64; 272 return teleport(xx, yy, zz); 273} 274 275bool EnderMan::teleportTowards(shared_ptr<Entity> e) 276{ 277 Vec3 *dir = Vec3::newTemp(x - e->x, bb->y0 + bbHeight / 2 - e->y + e->getHeadHeight(), z - e->z); 278 dir = dir->normalize(); 279 double d = 16; 280 double xx = x + (random->nextDouble() - 0.5) * 8 - dir->x * d; 281 double yy = y + (random->nextInt(16) - 8) - dir->y * d; 282 double zz = z + (random->nextDouble() - 0.5) * 8 - dir->z * d; 283 return teleport(xx, yy, zz); 284} 285 286bool EnderMan::teleport(double xx, double yy, double zz) 287{ 288 double xo = x; 289 double yo = y; 290 double zo = z; 291 292 x = xx; 293 y = yy; 294 z = zz; 295 bool ok = false; 296 int xt = Mth::floor(x); 297 int yt = Mth::floor(y); 298 int zt = Mth::floor(z); 299 300 if (level->hasChunkAt(xt, yt, zt)) 301 { 302 bool landed = false; 303 while (!landed && yt > 0) 304 { 305 int t = level->getTile(xt, yt - 1, zt); 306 if (t == 0 || !(Tile::tiles[t]->material->blocksMotion())) 307 { 308 y--; 309 yt--; 310 } 311 else 312 { 313 landed = true; 314 } 315 } 316 if (landed) 317 { 318 setPos(x, y, z); 319 if (level->getCubes(shared_from_this(), bb)->empty() && !level->containsAnyLiquid(bb)) 320 { 321 ok = true; 322 } 323 } 324 } 325 326 327 if (ok) 328 { 329 int count = 128; 330 for (int i = 0; i < count; i++) 331 { 332 double d = i / (count - 1.0); 333 float xa = (random->nextFloat() - 0.5f) * 0.2f; 334 float ya = (random->nextFloat() - 0.5f) * 0.2f; 335 float za = (random->nextFloat() - 0.5f) * 0.2f; 336 337 double _x = xo + (x - xo) * d + (random->nextDouble() - 0.5) * bbWidth * 2; 338 double _y = yo + (y - yo) * d + random->nextDouble() * bbHeight; 339 double _z = zo + (z - zo) * d + (random->nextDouble() - 0.5) * bbWidth * 2; 340 341 level->addParticle(eParticleType_ender, _x, _y, _z, xa, ya, za); 342 } 343 level->playSound(xo, yo, zo, eSoundType_MOB_ENDERMEN_PORTAL, 1, 1); 344 playSound(eSoundType_MOB_ENDERMEN_PORTAL, 1, 1); 345 return true; 346 } 347 else 348 { 349 setPos(xo, yo, zo); 350 return false; 351 } 352} 353 354int EnderMan::getAmbientSound() 355{ 356 return isCreepy()? eSoundType_MOB_ENDERMAN_SCREAM : eSoundType_MOB_ENDERMEN_IDLE; 357} 358 359int EnderMan::getHurtSound() 360{ 361 return eSoundType_MOB_ENDERMEN_HIT; 362} 363 364int EnderMan::getDeathSound() 365{ 366 return eSoundType_MOB_ENDERMEN_DEATH; 367} 368 369int EnderMan::getDeathLoot() 370{ 371 return Item::enderPearl_Id; 372} 373 374void EnderMan::dropDeathLoot(bool wasKilledByPlayer, int playerBonusLevel) 375{ 376 int loot = getDeathLoot(); 377 if (loot > 0) 378 { 379 int count = random->nextInt(2 + playerBonusLevel); 380 for (int i = 0; i < count; i++) 381 spawnAtLocation(loot, 1); 382 } 383} 384 385// 4J Brought forward from 1.2.3 to help fix Enderman behaviour 386void EnderMan::setCarryingTile(int carryingTile) 387{ 388 entityData->set(DATA_CARRY_ITEM_ID, (byte) (carryingTile & 0xff)); 389} 390 391int EnderMan::getCarryingTile() 392{ 393 return entityData->getByte(DATA_CARRY_ITEM_ID); 394} 395 396void EnderMan::setCarryingData(int carryingData) 397{ 398 entityData->set(DATA_CARRY_ITEM_DATA, (byte) (carryingData & 0xff)); 399} 400 401int EnderMan::getCarryingData() 402{ 403 return entityData->getByte(DATA_CARRY_ITEM_DATA); 404} 405 406bool EnderMan::hurt(DamageSource *source, float damage) 407{ 408 if (isInvulnerable()) return false; 409 setCreepy(true); 410 411 if ( dynamic_cast<EntityDamageSource *>(source) != NULL && source->getEntity()->instanceof(eTYPE_PLAYER)) 412 { 413 aggroedByPlayer = true; 414 } 415 416 if (dynamic_cast<IndirectEntityDamageSource *>(source) != NULL) 417 { 418 aggroedByPlayer = false; 419 for (int i = 0; i < 64; i++) 420 { 421 if (teleport()) 422 { 423 return true; 424 } 425 } 426 return false; 427 } 428 return Monster::hurt(source, damage); 429} 430 431bool EnderMan::isCreepy() 432{ 433 return entityData->getByte(DATA_CREEPY) > 0; 434} 435 436void EnderMan::setCreepy(bool creepy) 437{ 438 entityData->set(DATA_CREEPY, (byte)(creepy ? 1 : 0)); 439}