#include "stdafx.h" #include "net.minecraft.world.entity.ai.village.h" #include "net.minecraft.world.entity.h" #include "net.minecraft.world.entity.monster.h" #include "net.minecraft.world.level.h" #include "VillageSiege.h" VillageSiege::VillageSiege(Level *level) { hasSetupSiege = false; siegeState = SIEGE_NOT_INITED; siegeCount = 0; nextSpawnTime = 0; village = weak_ptr(); spawnX = spawnY = spawnZ = 0; this->level = level; } void VillageSiege::tick() { bool debug = false; if (debug) { if (siegeState == SIEGE_DONE) { siegeCount = 100; return; } // return; } else { if (level->isDay()) { siegeState = SIEGE_CAN_ACTIVATE; return; } if (siegeState == SIEGE_DONE) return; if (siegeState == SIEGE_CAN_ACTIVATE) { float timeOfDay = level->getTimeOfDay(0); if (timeOfDay < 0.50 || timeOfDay > 0.501) return; siegeState = level->random->nextInt(10) == 0 ? SIEGE_TONIGHT : SIEGE_DONE; hasSetupSiege = false; if (siegeState == SIEGE_DONE) return; } } if (!hasSetupSiege) { if (tryToSetupSiege()) hasSetupSiege = true; else return; } // Siege! if (nextSpawnTime > 0) { --nextSpawnTime; return; } nextSpawnTime = 2; // 50 + level.random.nextInt(100); if (siegeCount > 0) { trySpawn(); --siegeCount; } else { siegeState = SIEGE_DONE; } } bool VillageSiege::tryToSetupSiege() { vector > *players = &level->players; //for (Player player : players) for(AUTO_VAR(it, players->begin()); it != players->end(); ++it) { shared_ptr player = *it; shared_ptr _village = level->villages->getClosestVillage((int) player->x, (int) player->y, (int) player->z, 1); village = _village; if (_village == NULL) continue; if (_village->getDoorCount() < 10) continue; if (_village->getStableAge() < 20) continue; if (_village->getPopulationSize() < 20) continue; // setup siege origin Pos *center = _village->getCenter(); float radius = _village->getRadius(); bool overlaps = false; for (int i = 0; i < 10; ++i) { spawnX = center->x + (int) (Mth::cos(level->random->nextFloat() * PI * 2.f) * radius * 0.9); spawnY = center->y; spawnZ = center->z + (int) (Mth::sin(level->random->nextFloat() * PI * 2.f) * radius * 0.9); overlaps = false; vector > *villages = level->villages->getVillages(); //for (Village v : level.villages.getVillages()) for(AUTO_VAR(itV, villages->begin()); itV != villages->end(); ++itV) { shared_ptrv = *itV; if (v == _village) continue; if (v->isInside(spawnX, spawnY, spawnZ)) { overlaps = true; break; } } if (!overlaps) break; } if (overlaps) return false; Vec3 *spawnPos = findRandomSpawnPos(spawnX, spawnY, spawnZ); if (spawnPos == NULL) continue; nextSpawnTime = 0; siegeCount = 20; return true; } return false; } bool VillageSiege::trySpawn() { Vec3 *spawnPos = findRandomSpawnPos(spawnX, spawnY, spawnZ); if (spawnPos == NULL) return false; shared_ptr mob; //try { mob = shared_ptr( new Zombie(level) ); mob->finalizeMobSpawn(); mob->setVillager(false); } //catch (Exception e) { // e.printStackTrace(); // return false; //} mob->moveTo(spawnPos->x, spawnPos->y, spawnPos->z, level->random->nextFloat() * 360, 0); level->addEntity(mob); shared_ptr _village = village.lock(); if( _village == NULL ) return false; Pos *center = _village->getCenter(); mob->restrictTo(center->x, center->y, center->z, _village->getRadius()); return true; } Vec3 *VillageSiege::findRandomSpawnPos(int x, int y, int z) { shared_ptr _village = village.lock(); if( _village == NULL ) return NULL; for (int i = 0; i < 10; ++i) { int xx = x + level->random->nextInt(16) - 8; int yy = y + level->random->nextInt(6) - 3; int zz = z + level->random->nextInt(16) - 8; if (!_village->isInside(xx, yy, zz)) continue; if (MobSpawner::isSpawnPositionOk(MobCategory::monster, level, xx, yy, zz)) return Vec3::newTemp(xx, yy, zz); } return NULL; }