diff --git a/hwe/sammo/Event/Action/RaiseNPCNation.php b/hwe/sammo/Event/Action/RaiseNPCNation.php new file mode 100644 index 00000000..76670291 --- /dev/null +++ b/hwe/sammo/Event/Action/RaiseNPCNation.php @@ -0,0 +1,276 @@ + $rhs[1]; + }); + + + //최소, 최대 도시 몇개를 뺀다. 정렬은 신경쓰지 않는다. + + if ($cityCnt >= 3) { + $reduceCnt = Util::valueFit(Util::round($cityCnt / 6, 0), 1); + foreach (Util::range($reduceCnt) as $_idx) { + array_pop($targetCities); + } + + foreach (Util::range($reduceCnt) as $idx) { + $targetCities[$idx] = array_pop($targetCities); + } + + $cityCnt -= $reduceCnt * 2; + } + + $avgCity = []; + foreach ($targetCities as $city) { + foreach (static::CITY_KEYS as $key) { + $avgCity[$key] = ($avgCity[$key] ?? 0) + $city[$key]; + } + } + + foreach (static::CITY_KEYS as $key) { + $avgCity[$key] = Util::toInt($avgCity[$key] / $cityCnt); + } + return $avgCity; + } + + public function calcAvgNationGeneralCnt(): int + { + $nationUsers = []; + foreach (\sammo\getAllNationStaticInfo() as $nation) { + if ($nation['level'] == 0) { + continue; + } + $nationUsers[] = $nation['gennum']; + } + + $nationCnt = count($nationUsers); + if ($nationCnt == 0) { + return GameConst::$initialNationGenLimit; + } + + sort($nationUsers); + if ($nationCnt >= 3) { + $reduceCnt = Util::valueFit(Util::round($nationCnt / 6, 0), 1); + foreach (Util::range($reduceCnt) as $_idx) { + array_pop($nationUsers); + } + + foreach (Util::range($reduceCnt) as $idx) { + $nationUsers[$idx] = array_pop($nationUsers); + } + $nationCnt -= $reduceCnt * 2; + } + + return Util::round(array_sum($nationUsers) / $nationCnt); + } + + public function calcAvgTech(): int + { + $techSum = 0; + $nationCnt = 0; + foreach (\sammo\getAllNationStaticInfo() as $nation) { + if ($nation['level'] == 0) { + continue; + } + $techSum += $nation['tech']; + $nationCnt += 1; + } + if($nationCnt == 0){ + return 0; + } + return Util::toInt($techSum / $nationCnt); + } + + private function buildNation(int $nationID, int $tech, array $baseCity, array $avgCity, int $genCnt, $env) + { + $db = DB::db(); + + $targetCity = [ + 'trust' => 100 + ]; + foreach (static::CITY_KEYS as $key) { + $targetCity[$key] = min($targetCity["{$key}_max"], $avgCity[$key]); + } + + $pickTypeList = ['무' => 1, '지' => 1]; + + $cityID = $baseCity['id']; + $cityName = $baseCity['name']; + $nationName = "ⓤ{$cityName}"; + + $color = Util::choiceRandom(GetNationColors()); + $nationObj = new Nation($nationID, $nationName, $color, 0, 2000, "우리도 할 수 있다! {$cityName}군", $tech, null, 2, [$cityName]); + $nationObj->build($env); + + $affinity = Util::randRangeInt(1, 150); + $ruler = (new GeneralBuilder("{$cityName}태수", false, null, $nationID)) + ->setOfficerLevel(12) + ->setCityID($cityID) + ->setNPCType(6) + ->setGoldRice(1000, 1000) + ->setAffinity($affinity) + ->fillRandomStat($pickTypeList) + ->fillRemainSpecAsZero($env); + $ruler->build($env); + + $nationObj->addGeneral($ruler); + + foreach (pickGeneralFromPool(DB::db(), 0, $genCnt - 1) as $pickedNPC) { + $newNPC = $pickedNPC->getGeneralBuilder(); + $newNPC->setNationID($nationID) + ->setCityID($cityID) + ->setNPCType(6) + ->setGoldRice(1000, 1000) + ->setAffinity($affinity) + ->fillRandomStat($pickTypeList) + ->fillRemainSpecAsZero($env); + $newNPC->build($env); + $pickedNPC->occupyGeneralName(); + + $nationObj->addGeneral($newNPC); + } + + $nationObj->postBuild($env); + $db->update('city', $targetCity, 'city = %i', $cityID); + refreshNationStaticInfo(); + } + + public function run(array $env) + { + $db = DB::db(); + + $allCities = $db->query('SELECT * FROM city WHERE 5 <= level AND level <= 6'); //소, 중 성만 선택 + + $emptyCities = []; + $occupiedCities = []; + $npcCities = []; + + $avgCity = $this->calcAvgNationCity($allCities); + + foreach ($allCities as $city) { + if ($city['nation'] == 0) { + $emptyCities[$city['city']] = $city; + } else { + $occupiedCities[$city['city']] = $city; + } + } + + $avgGenCnt = $this->calcAvgNationGeneralCnt(); + + $serverID = UniqueConst::$serverID; + $existNations = $db->queryFirstColumn("SELECT nation FROM `nation`"); + $lastNationID = max( + max($existNations), + $db->queryFirstField("SELECT max(`nation`) FROM `ng_old_nations` WHERE server_id = %s", $serverID), + ); + + $avgTech = $this->calcAvgTech(); + Util::shuffle_assoc($emptyCities); + + $occupiedCitiesID = array_keys($occupiedCities); + $npcCitiesID = []; + + foreach ($emptyCities as $emptyCity) { + $cityID = $emptyCity['city']; + + $minDistance = 999; + foreach($occupiedCitiesID as $targetCityID){ + $minDistance = min(\sammo\calcCityDistance($cityID, $targetCityID, null), $minDistance); + if($minDistance < static::MIN_DIST_USERNATION){ + break; + } + } + if($minDistance < static::MIN_DIST_USERNATION){ + continue; + } + + $minDistance = 999; + foreach($npcCitiesID as $targetCityID){ + $minDistance = min(\sammo\calcCityDistance($cityID, $targetCityID, null), $minDistance); + if($minDistance < static::MIN_DIST_NPCNATION){ + break; + } + } + if($minDistance < static::MIN_DIST_NPCNATION){ + continue; + } + + //TODO: 거리 측정 + $lastNationID += 1; + $this->buildNation($lastNationID, $avgTech, $emptyCity, $avgCity, $avgGenCnt, $env); + $npcCities[$cityID] = $emptyCity; + $npcCitiesID[] = $cityID; + } + + if(count($npcCities) > 0){ + $logger = new ActionLogger(0, 0, $env['year'], $env['month']); + $logger->pushGlobalHistoryLog("【공지】공백지에 임의의 국가가 생성되었습니다."); + $logger->flush(); + } + + return [__CLASS__, count($npcCities)]; + } +}