the game where you go into mines and start crafting! but for consoles (forked directly from smartcmd's github)
at main 258 lines 5.2 kB view raw
1#include "stdafx.h" 2#include "net.minecraft.world.entity.h" 3#include "net.minecraft.world.entity.ai.attributes.h" 4#include "net.minecraft.world.entity.monster.h" 5#include "net.minecraft.world.level.h" 6#include "net.minecraft.world.level.tile.h" 7#include "net.minecraft.world.phys.h" 8#include "Bat.h" 9 10Bat::Bat(Level *level) : AmbientCreature(level) 11{ 12 // 4J Stu - This function call had to be moved here from the Entity ctor to ensure that 13 // the derived version of the function is called 14 this->defineSynchedData(); 15 registerAttributes(); 16 setHealth(getMaxHealth()); 17 18 targetPosition = NULL; 19 20 setSize(.5f, .9f); 21 setResting(true); 22} 23 24void Bat::defineSynchedData() 25{ 26 AmbientCreature::defineSynchedData(); 27 28 entityData->define(DATA_ID_FLAGS, (char) 0); 29} 30 31float Bat::getSoundVolume() 32{ 33 return 0.1f; 34} 35 36float Bat::getVoicePitch() 37{ 38 return AmbientCreature::getVoicePitch() * .95f; 39} 40 41int Bat::getAmbientSound() 42{ 43 if (isResting() && random->nextInt(4) != 0) 44 { 45 return -1; 46 } 47 return eSoundType_MOB_BAT_IDLE; //"mob.bat.idle"; 48} 49 50int Bat::getHurtSound() 51{ 52 return eSoundType_MOB_BAT_HURT; //"mob.bat.hurt"; 53} 54 55int Bat::getDeathSound() 56{ 57 return eSoundType_MOB_BAT_DEATH; //"mob.bat.death"; 58} 59 60bool Bat::isPushable() 61{ 62 // bats can't be pushed by other mobs 63 return false; 64} 65 66void Bat::doPush(shared_ptr<Entity> e) 67{ 68 // bats don't push other mobs 69} 70 71void Bat::pushEntities() 72{ 73 // bats don't push other mobs 74} 75 76void Bat::registerAttributes() 77{ 78 AmbientCreature::registerAttributes(); 79 80 getAttribute(SharedMonsterAttributes::MAX_HEALTH)->setBaseValue(6); 81} 82 83bool Bat::isResting() 84{ 85 return (entityData->getByte(DATA_ID_FLAGS) & FLAG_RESTING) != 0; 86} 87 88void Bat::setResting(bool value) 89{ 90 char current = entityData->getByte(DATA_ID_FLAGS); 91 if (value) 92 { 93 entityData->set(DATA_ID_FLAGS, (char) (current | FLAG_RESTING)); 94 } 95 else 96 { 97 entityData->set(DATA_ID_FLAGS, (char) (current & ~FLAG_RESTING)); 98 } 99} 100 101bool Bat::useNewAi() 102{ 103 return true; 104} 105 106void Bat::tick() 107{ 108 109 AmbientCreature::tick(); 110 111 if (isResting()) 112 { 113 xd = yd = zd = 0; 114 y = Mth::floor(y) + 1.0 - bbHeight; 115 } 116 else 117 { 118 yd *= .6f; 119 } 120 121} 122 123inline int signum(double x) { return (x > 0) - (x < 0); } 124 125void Bat::newServerAiStep() 126{ 127 AmbientCreature::newServerAiStep(); 128 129 if (isResting()) 130 { 131 if (!level->isSolidBlockingTile(Mth::floor(x), (int) y + 1, Mth::floor(z))) 132 { 133 setResting(false); 134 level->levelEvent(nullptr, LevelEvent::SOUND_BAT_LIFTOFF, (int) x, (int) y, (int) z, 0); 135 } 136 else 137 { 138 139 if (random->nextInt(200) == 0) 140 { 141 yHeadRot = random->nextInt(360); 142 } 143 144 if (level->getNearestPlayer(shared_from_this(), 4.0f) != NULL) 145 { 146 setResting(false); 147 level->levelEvent(nullptr, LevelEvent::SOUND_BAT_LIFTOFF, (int) x, (int) y, (int) z, 0); 148 } 149 } 150 } 151 else 152 { 153 154 if (targetPosition != NULL && (!level->isEmptyTile(targetPosition->x, targetPosition->y, targetPosition->z) || targetPosition->y < 1)) 155 { 156 delete targetPosition; 157 targetPosition = NULL; 158 } 159 if (targetPosition == NULL || random->nextInt(30) == 0 || targetPosition->distSqr((int) x, (int) y, (int) z) < 4) 160 { 161 delete targetPosition; 162 targetPosition = new Pos((int) x + random->nextInt(7) - random->nextInt(7), (int) y + random->nextInt(6) - 2, (int) z + random->nextInt(7) - random->nextInt(7)); 163 } 164 165 double dx = (targetPosition->x + .5) - x; 166 double dy = (targetPosition->y + .1) - y; 167 double dz = (targetPosition->z + .5) - z; 168 169 xd = xd + (signum(dx) * .5f - xd) * .1f; 170 yd = yd + (signum(dy) * .7f - yd) * .1f; 171 zd = zd + (signum(dz) * .5f - zd) * .1f; 172 173 float yRotD = (float) (atan2(zd, xd) * 180 / PI) - 90; 174 float rotDiff = Mth::wrapDegrees(yRotD - yRot); 175 yya = .5f; 176 yRot += rotDiff; 177 178 if (random->nextInt(100) == 0 && level->isSolidBlockingTile(Mth::floor(x), (int) y + 1, Mth::floor(z))) 179 { 180 setResting(true); 181 } 182 183 } 184} 185 186bool Bat::makeStepSound() 187{ 188 return false; 189} 190 191void Bat::causeFallDamage(float distance) 192{ 193} 194 195void Bat::checkFallDamage(double ya, bool onGround) 196{ 197 // this method is empty because flying creatures should 198 // not trigger the "fallOn" tile calls (such as trampling crops) 199} 200 201bool Bat::isIgnoringTileTriggers() 202{ 203 return true; 204} 205 206bool Bat::hurt(DamageSource *source, float dmg) 207{ 208 if (isInvulnerable()) return false; 209 if (!level->isClientSide) 210 { 211 if (isResting()) 212 { 213 setResting(false); 214 } 215 } 216 217 return AmbientCreature::hurt(source, dmg); 218} 219 220void Bat::readAdditionalSaveData(CompoundTag *tag) 221{ 222 AmbientCreature::readAdditionalSaveData(tag); 223 224 entityData->set(DATA_ID_FLAGS, tag->getByte(L"BatFlags")); 225} 226 227void Bat::addAdditonalSaveData(CompoundTag *entityTag) 228{ 229 AmbientCreature::addAdditonalSaveData(entityTag); 230 231 entityTag->putByte(L"BatFlags", entityData->getByte(DATA_ID_FLAGS)); 232} 233 234 235bool Bat::canSpawn() 236{ 237 int yt = Mth::floor(bb->y0); 238 if (yt >= level->seaLevel) return false; 239 240 int xt = Mth::floor(x); 241 int zt = Mth::floor(z); 242 243 int br = level->getRawBrightness(xt, yt, zt); 244 int maxLight = 4; 245 246 if ((Calendar::GetDayOfMonth() + 1 == 10 && Calendar::GetDayOfMonth() >= 20) || (Calendar::GetMonth() + 1 == 11 && Calendar::GetMonth() <= 3)) 247 { 248 maxLight = 7; 249 } 250 else if (random->nextBoolean()) 251 { 252 return false; 253 } 254 255 if (br > random->nextInt(maxLight)) return false; 256 257 return AmbientCreature::canSpawn(); 258}