npcEachCount = $npcEachCount; $this->specAvg = $specAvg; $this->tech = $tech; $this->dex = $dex; } private function moveCapital(RandUtil $rng): Set { $cities = []; foreach (CityConst::all() as $cityObj) { if ($cityObj->level != 4) { continue; } $cities[] = $cityObj->id; } $disabledInvaderCity = new Set(); if (count($cities) == 0) { return $disabledInvaderCity; } $db = DB::db(); foreach ($db->queryAllLists('SELECT capital, nation from nation WHERE capital in %li', $cities) as $row) { [$oldCapital, $nation] = $row; $capitalCandidates = $db->queryFirstColumn('SELECT city from city WHERE nation = %i AND city != %i AND city NOT IN %li', $nation, $oldCapital, $cities); if (!$capitalCandidates) { $disabledInvaderCity->add($oldCapital); continue; } $newCapital = $rng->choice($capitalCandidates); $db->update('nation', ['capital' => $newCapital], 'nation=%i', $nation); $db->update('general', ['city' => $newCapital], 'nation=%i and city=%i', $nation, $oldCapital); } $db->update('general', [ 'officer_level' => 1, 'officer_city' => 0 ], 'officer_city in %li', $cities); $db->update('city', [ 'nation' => 0, 'front' => 0, 'supply' => 1, ], 'city in %li', $cities); if(!$disabledInvaderCity->isEmpty()){ refreshNationStaticInfo(); } return $disabledInvaderCity; } public function run(array $env) { $db = DB::db(); $npcEachCount = $this->npcEachCount; /** @var \sammo\CityInitDetail[] */ $cities = []; foreach (CityConst::all() as $cityObj) { if ($cityObj->level != 4) { continue; } $cities[] = $cityObj; } if(!$cities){ return [__CLASS__, 0]; } $gameStor = KVStorage::getStorage($db, 'game_env'); $gameStor->setValue('isunited', 1); $turnterm = $gameStor->turnterm; $generalCnt = $db->queryFirstField('SELECT count(*) FROM general'); if ($npcEachCount < 0) { $npcEachCount = $db->queryFirstField('SELECT count(no) from general where npc < 4') / count($cities); $npcEachCount *= -1 * $this->npcEachCount; } $npcEachCount = max(10, Util::toInt($npcEachCount)); $totalGenerals = $npcEachCount * count($cities) + $generalCnt; if ($totalGenerals > ServerEnv::$maxGeneralsPerMinute * $turnterm) { foreach ([1, 2, 5, 10, 20, 30, 60, 120] as $nextTurnterm) { if ($totalGenerals > ServerEnv::$maxGeneralsPerMinute * $nextTurnterm) { continue; } ServerTool::changeServerTerm($nextTurnterm, true); break; } } $specAvg = $this->specAvg; if ($specAvg < 0) { $specAvg = $db->queryFirstField('SELECT avg((`leadership` + `strength` + `intel`)) from general where npc < 4'); $specAvg *= -1 * $this->specAvg; } $specAvg = Util::toInt($specAvg / 3); $tech = $this->tech; if ($tech < 0) { $tech = $db->queryFirstField("SELECT avg(tech) from nation where `level`>0"); $tech *= -1 * $this->tech; } $dex = $this->dex; if ($dex < 0) { $dex = $db->queryFirstField("SELECT avg((dex1 + dex2 + dex3 + dex4 + dex5)/5) from general where npc < 4"); $dex *= -1 * $this->dex; } $dex = Util::toInt($dex); $year = $env['year']; $month = $env['month']; $rng = new RandUtil(new LiteHashDRBG(Util::simpleSerialize( UniqueConst::$hiddenSeed, 'RaiseInvader', $year, $month, ))); $db->update('nation', [ 'war' => 0, 'scout' => 0, ], '1'); $disabledInvaderCity = $this->moveCapital($rng); $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), ); $exp = $db->queryFirstField("SELECT avg(experience) from general where npc < 6"); $db->update('general', [ 'gold' => 999999, 'rice' => 999999, ], true); $invaderNationIDList = []; refreshNationStaticInfo(); foreach ($cities as $cityObj) { if ($cityObj->level != 4) { continue; } if($disabledInvaderCity->contains($cityObj->id)){ continue; } $lastNationID += 1; $invaderNationID = $lastNationID; $invaderNationIDList[] = $invaderNationID; $invaderName = $cityObj->name; $nationName = "ⓞ{$invaderName}족"; $nationObj = new Nation($rng, $invaderNationID, $nationName, '#800080', 9999999, 9999999, "중원의 부패를 물리쳐라! 이민족 침범!", $tech, "che_병가", 2, [$cityObj->name]); $nationObj->build($env); $ruler = (new GeneralBuilder($rng, "{$invaderName}대왕", false, null, $lastNationID)) ->setEgo('che_패권') ->setSpecial('che_인덕', 'che_척사') ->setLifeSpan($year - 20, $year + 20) ->setCityID($cityObj->id) ->setNPCType(9) ->setStat(Util::toInt($specAvg * 1.8), Util::toInt($specAvg * 1.8), Util::toInt($specAvg * 1.2)) ->setAffinity(999) ->setExpDed(Util::toInt($exp * 1.2), null) ->setGoldRice(99999, 99999); $ruler->build($env); $nationObj->addGeneral($ruler); foreach (Util::range(1, $npcEachCount) as $invaderGenIdx) { $gen = (new GeneralBuilder($rng, "{$invaderName}장수{$invaderGenIdx}", false, null, $invaderNationID)) ->setEgo('che_패권') ->setSpecial('che_인덕', 'che_척사') ->setLifeSpan($year - 20, $year + 20) ->setCityID($cityObj->id) ->setNPCType(9) ->setAffinity(999) ->setExpDed($exp, null) ->setGoldRice(99999, 99999); $leadership = $rng->nextRangeInt(Util::toInt($specAvg * 1.2), Util::toInt($specAvg * 1.4)); $mainStat = $rng->nextRangeInt(Util::toInt($specAvg * 1.2), Util::toInt($specAvg * 1.4)); $subStat = $specAvg * 3 - $leadership - $mainStat; if ($rng->nextBit()) { //무장 $dexTable = [$dex * 2, $dex, $dex]; shuffle($dexTable); $gen->setStat($leadership, $mainStat, $subStat) ->setDex($dexTable[0], $dexTable[1], $dexTable[2], $dex, 0); } else { //지장 $gen->setStat($leadership, $subStat, $mainStat) ->setDex($dex, $dex, $dex, $dex * 2, 0); } $gen->build($env); $nationObj->addGeneral($gen); } $nationObj->postBuild($env); refreshNationStaticInfo(); $db->insert('event', [ 'target' => 'month', 'priority' => 1000, 'condition' => Json::encode(true), 'action' => Json::encode([["AutoDeleteInvader", $invaderNationID]]), ]); } $db->insert('event', [ 'target' => 'month', 'priority' => 1000, 'condition' => Json::encode(true), 'action' => Json::encode([["InvaderEnding"]]), ]); $db->update('diplomacy', [ 'state' => 1, 'term' => 24, ], '(me IN %li AND you IN %li) OR (me IN %li AND you IN %li)', $existNations, $invaderNationIDList, $invaderNationIDList, $existNations); $db->update('diplomacy', [ 'state' => 7, 'term' => 480, ], '(me IN %li AND you IN %li)', $invaderNationIDList, $invaderNationIDList); $cityMaxPop = $specAvg * $npcEachCount * 100 * 4; $db->update('city', [ 'pop_max' => $cityMaxPop, 'def_max' => 100000, 'wall_max' => 10000, ], 'nation IN %li', $invaderNationIDList); $db->update('city', [ 'pop' => $db->sqleval('pop_max'), 'agri' => $db->sqleval('agri_max'), 'comm' => $db->sqleval('comm_max'), 'secu' => $db->sqleval('secu_max'), ], true); refreshNationStaticInfo(); $logger = new ActionLogger(0, 0, $year, $env['month']); $logger->pushGlobalHistoryLog("【이벤트】각지의 이민족들이 궐기합니다!"); $logger->pushGlobalHistoryLog("【이벤트】중원의 전 국가에 선전포고 합니다!"); $logger->pushGlobalHistoryLog("【이벤트】이민족의 기세는 그 누구도 막을 수 없을듯 합니다!"); $logger->flush(); $gameStor->setValue('block_change_scout', false); $db->update('plock', [ 'plock' => 0 ], true); return [__CLASS__, count($invaderNationIDList)]; } }