유산 포인트 시스템, 추가 기수 대비 (#187)
- 유산 포인트 - 기수 뒤로도 누적되는 포인트 - 생존, 최대 임관년 수, 최대 연속 내정 성공, 병종 상성 우위 횟수, 전투 횟수, 계략 성공 횟수, 천통 기여(규모 상승, 천통 수뇌, 천통 군주), 숙련도, 토너먼트, 베팅 당첨 - 유산 관리 페이지 제공 - 태수국 - 181년 1월에 자동 생성되는 u장수국 - 시간이 지나면 사실상 자동 소멸 - 유저국과는 4칸 거리, 서로는 2칸 거리 - 이 시스템으로 인해 m장 거병 차단 - NPC 원조시 불가침 - 1년 세수만큼 받은 경우 24개월 불가침 제안 - 최소 6개월 - 불가침을 받지 않고 추가 원조한 경우 계속해서 기간 상승 - 단, 불가침 수락 전에 선포를 할 수 있음 Reviewed-on: https://storage.hided.net/gitea/devsam/core/pulls/187 Co-authored-by: hide_d <hided62@gmail.com> Co-committed-by: hide_d <hided62@gmail.com>
This commit is contained in:
@@ -0,0 +1,18 @@
|
||||
{
|
||||
"presets": [
|
||||
[
|
||||
"@babel/preset-env",
|
||||
{
|
||||
"targets": {
|
||||
"browsers": [
|
||||
"last 2 versions"
|
||||
]
|
||||
},
|
||||
"modules":false
|
||||
}
|
||||
]
|
||||
],
|
||||
"plugins": [
|
||||
"lodash"
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
module.exports = {
|
||||
root: true,
|
||||
parser: "@typescript-eslint/parser",
|
||||
parserOptions: {
|
||||
"project": "./tsconfig.json"
|
||||
},
|
||||
ignorePatterns: ['*.test.ts', '.eslintrc.js', 'webpack.config.js', '*.js'],
|
||||
overrides: [{
|
||||
files: ['*.ts', '*.tsx'],
|
||||
}],
|
||||
plugins: [
|
||||
"@typescript-eslint",
|
||||
],
|
||||
extends: [
|
||||
"eslint:recommended",
|
||||
"plugin:@typescript-eslint/eslint-recommended",
|
||||
"plugin:@typescript-eslint/recommended"
|
||||
],
|
||||
rules: {
|
||||
'@typescript-eslint/no-floating-promises': 'error',
|
||||
}
|
||||
}
|
||||
+2
-1
@@ -4,7 +4,8 @@
|
||||
!.vscode/launch.json
|
||||
!.vscode/extensions.json
|
||||
|
||||
|
||||
/node_modules
|
||||
package-lock.json
|
||||
|
||||
|
||||
# 체섭 ignore
|
||||
|
||||
@@ -24,3 +24,7 @@ foreach ($db->queryFirstColumn(
|
||||
) as $generalNo) {
|
||||
CheckHall($generalNo);
|
||||
}
|
||||
|
||||
foreach(General::createGeneralObjListFromDB($db->queryFirstColumn('SELECT `no` FROM general WHERE npc = 0')) as $genObj){
|
||||
$genObj->mergeTotalInheritancePoint();
|
||||
}
|
||||
@@ -0,0 +1,131 @@
|
||||
<?php
|
||||
|
||||
namespace sammo;
|
||||
|
||||
include "lib.php";
|
||||
include "func.php";
|
||||
//로그인 검사
|
||||
$session = Session::requireGameLogin()->setReadOnly();
|
||||
$userID = Session::getUserID();
|
||||
$generalID = $session->generalID;
|
||||
|
||||
$db = DB::db();
|
||||
$gameStor = KVStorage::getStorage($db, 'game_env');
|
||||
|
||||
$me = General::createGeneralObjFromDB($generalID);
|
||||
|
||||
|
||||
$pointHelpText = [
|
||||
'sum' => '다음 플레이에서 사용할 수 있는 총 포인트입니다.',
|
||||
'new' => '이번 플레이에서 얻은 총 포인트입니다.',
|
||||
'previous' => '이전에 물려받은 포인트입니다.',
|
||||
'lived_month' => '살아남은 기간입니다. (1개월 단위)',
|
||||
'max_belong' => '가장 오래 임관했던 국가의 연도입니다.',
|
||||
'max_domestic_critical' => '성공한 내정 중 최대 연속값입니다.',
|
||||
'snipe_combat' => '유리한 상성을 가지고 전투했습니다.',
|
||||
'combat' => '전투 횟수입니다.',
|
||||
'sabotage' => '계략 성공 횟수입니다.',
|
||||
'unifier' => '천통에 기여한 포인트입니다. <br>각 국의 군주, 천통 수뇌, 천통 군주가 받습니다.',
|
||||
'dex' => '총 숙련도합입니다.',
|
||||
'tournament' => '토너먼트 입상 포인트입니다.',
|
||||
'betting' => '성공적인 베팅을 했습니다. <br>수익율과 베팅 성공 횟수를 따릅니다.',
|
||||
];
|
||||
$items = [];
|
||||
foreach(array_keys(General::INHERITANCE_KEY) as $key){
|
||||
$items[$key] = $me->getInheritancePoint($key)??0;
|
||||
}
|
||||
?>
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<title><?= UniqueConst::$serverName ?>: 유산 관리</title>
|
||||
<meta charset="UTF-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<meta name="viewport" content="width=1024" />
|
||||
<?= WebUtil::printCSS('../e_lib/bootstrap.min.css') ?>
|
||||
<?= WebUtil::printCSS('../d_shared/common.css') ?>
|
||||
<?= WebUtil::printCSS('../css/config.css') ?>
|
||||
<?= WebUtil::printCSS('css/common.css') ?>
|
||||
<?= WebUtil::printCSS('css/inheritPoint.css') ?>
|
||||
<?= WebUtil::printJS('../d_shared/common_path.js') ?>
|
||||
<?= WebUtil::printJS('../e_lib/jquery-3.3.1.min.js') ?>
|
||||
<?= WebUtil::printJS('../e_lib/bootstrap.bundle.min.js') ?>
|
||||
<?= WebUtil::printJS('js/common.js') ?>
|
||||
<?= WebUtil::printJS('js/inheritPoint.js') ?>
|
||||
<script>
|
||||
var items = <?=Json::encode($items)?>;
|
||||
var helpText = <?=Json::encode($pointHelpText)?>;
|
||||
</script>
|
||||
</head>
|
||||
|
||||
<body onload="formStart()">
|
||||
|
||||
<table style='width:1000px;margin:auto;' class='tb_layout bg0'>
|
||||
<tr>
|
||||
<td style='text-align:left;'>유산 관리<br><?= backButton() ?></td>
|
||||
</tr>
|
||||
</table>
|
||||
<div id="container" class="tb_layout bg0" style="width:1000px;margin:auto;border:solid 1px #888888;">
|
||||
<div id='inheritance_list'>
|
||||
<div id="inherit_sum" class='inherit_item'>
|
||||
<div class="row">
|
||||
<label id="inherit_sum_head" class='inherit_head col-sm-6 col-form-label'>총 포인트</label>
|
||||
<div class="col-sm-6">
|
||||
<input type="text" class="form-control inherit_value" readonly id="inherit_sum_value" value="">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div style="text-align:right">
|
||||
<small class="form-text text-muted"></small>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="inherit_previous" class='inherit_item'>
|
||||
<div class="row">
|
||||
<label id="inherit_sum_head" class='inherit_head col-sm-6 col-form-label'>기존 포인트</label>
|
||||
<div class="col-sm-6">
|
||||
<input type="text" class="form-control inherit_value" readonly id="inherit_previous_value" value="">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div style="text-align:right">
|
||||
<small class="form-text text-muted"></small>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="inherit_new" class='inherit_item'>
|
||||
<div class="row">
|
||||
<label id="inherit_sum_head" class='inherit_head col-sm-6 col-form-label'>신규 포인트</label>
|
||||
<div class="col-sm-6">
|
||||
<input type="text" class="form-control inherit_value" readonly id="inherit_new_value" value="">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div style="text-align:right">
|
||||
<small class="form-text text-muted"></small>
|
||||
</div>
|
||||
</div>
|
||||
<div style="width:100%; padding:0 10px"><hr style="border-top:1px solid #888888;"></div>
|
||||
<?php foreach (General::INHERITANCE_KEY as $key => [$type, $multiplier, $name]) : ?>
|
||||
<?php if ($key == 'previous') {
|
||||
continue;
|
||||
} ?>
|
||||
<div id="inherit_<?= $key ?>" class='inherit_item inherit_template_item'>
|
||||
<div class="row">
|
||||
<label id="inherit_<?= $key ?>_head" class='inherit_head col-sm-6 col-form-label'><?= $name ?></label>
|
||||
<div class="col-sm-6">
|
||||
<input type="text" class="form-control inherit_value" readonly id="inherit_<?= $key ?>_value" value="">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div style="text-align:right">
|
||||
<small class="form-text text-muted"></small>
|
||||
</div>
|
||||
</div>
|
||||
<?php endforeach; ?>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
@@ -91,6 +91,7 @@ $zeroPolicy = new AutorunNationPolicy($general, ($gameStor->autorun_user)['optio
|
||||
var availableGeneralActionPriorityItems = <?= Json::encode(AutorunGeneralPolicy::$default_priority) ?>;
|
||||
|
||||
var btnHelpMessage = {
|
||||
'불가침제의': '군주가 NPC이고, 타국에서 원조를 받았을 때,<br>세입(금/쌀) 대비 원조량에 따라 불가침제의를 합니다.',
|
||||
'선전포고': '군주가 NPC이고, 전쟁중이 아닐 때,<br>주변국중 하나를 골라 선포합니다.<br><br>선포 시점은 다음을 참고합니다.<br>- 인구율<br>- 도시내정률<br>- NPC전투장권장 금 충족률<br>- NPC전투장권장 쌀 충족률<br><br>국력이 낮은 국가를 조금 더 선호합니다.',
|
||||
'천도': '인구가 많은 곳을 찾아 천도를 시도합니다.<br>영토의 가운데를 선호합니다.<br><br>도시 인구가 충분하다면, 굳이 천도하지는 않습니다.',
|
||||
'유저장긴급포상': '금/쌀이 부족한 유저전투장에게 긴급하게 포상합니다.<br>국고가 권장량보다 적어지더라도 시도합니다.',
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
#inheritance_list{
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.inherit_padding{
|
||||
width: 33%;
|
||||
padding: 10px 2px;
|
||||
}
|
||||
|
||||
.inherit_item{
|
||||
width: 33%;
|
||||
padding: 10px 2px;
|
||||
}
|
||||
|
||||
.col-form-label{
|
||||
text-align:right;
|
||||
padding-right:2ch;
|
||||
}
|
||||
|
||||
.inherit_value{
|
||||
text-align: right;
|
||||
}
|
||||
+7
-1
@@ -1707,7 +1707,7 @@ function deleteNation(General $lord, bool $applyDB):array
|
||||
$nationID,
|
||||
$lordID
|
||||
),
|
||||
['npc', 'gold', 'rice', 'experience', 'explevel', 'dedication', 'dedlevel', 'aux'], 1
|
||||
['npc', 'gold', 'rice', 'experience', 'explevel', 'dedication', 'dedlevel', 'belong', 'aux'], 1
|
||||
);
|
||||
$nationGeneralList[$lordID] = $lord;
|
||||
|
||||
@@ -1724,6 +1724,12 @@ function deleteNation(General $lord, bool $applyDB):array
|
||||
|
||||
// 전 장수 재야로
|
||||
foreach($nationGeneralList as $general){
|
||||
$general->setAuxVar('max_belong',
|
||||
max(
|
||||
$general->getVar('belong'),
|
||||
$general->getAuxVar('max_belong')??0
|
||||
)
|
||||
);
|
||||
$general->setVar('belong', 0);
|
||||
$general->setVar('troop', 0);
|
||||
$general->setVar('officer_level', 0);
|
||||
|
||||
+40
-1
@@ -623,10 +623,14 @@ function updateNationState()
|
||||
$nation['nation'],
|
||||
$targetKillTurn
|
||||
);
|
||||
$nationGenList = General::createGeneralObjListFromDB($nationGenIDList, ['belong'], 2);
|
||||
$nationGenList = General::createGeneralObjListFromDB($nationGenIDList, ['belong', 'npc'], 2);
|
||||
$chiefObj = null;
|
||||
|
||||
$uniqueLotteryWeightList = [];
|
||||
foreach ($nationGenList as $nationGen) {
|
||||
if ($nationGen->getVar('officer_level') == 12) {
|
||||
$chiefObj = $nationGen;
|
||||
}
|
||||
$trialCnt = count(GameConst::$allItems);
|
||||
|
||||
foreach ($nationGen->getItems() as $item) {
|
||||
@@ -665,6 +669,10 @@ function updateNationState()
|
||||
giveRandomUniqueItem($winnerObj, '작위보상');
|
||||
$winnerObj->applyDB($db);
|
||||
}
|
||||
|
||||
if($chiefObj){
|
||||
$chiefObj->increaseInheritancePoint('unifier', 250 * $levelDiff);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -982,6 +990,15 @@ function checkEmperior()
|
||||
$nationLogger = new ActionLogger(0, $nationID, $admin['year'], $admin['month']);
|
||||
$nationLogger->pushNationalHistoryLog("<D><b>{$nationName}</b></>{$josaYi} 전토를 통일");
|
||||
|
||||
foreach(General::createGeneralObjListFromDB($db->queryFirstColumn('SELECT `no` FROM general WHERE npc = 0')) as $genObj){
|
||||
if($genObj->getNationID() == $nationID){
|
||||
if($genObj->getVar('officer_level') > 4){
|
||||
$genObj->increaseInheritancePoint('unifier', 2000);
|
||||
};
|
||||
}
|
||||
$genObj->mergeTotalInheritancePoint();
|
||||
}
|
||||
|
||||
$gameStor->isunited = 2;
|
||||
$gameStor->conlimit = $gameStor->conlimit * 100;
|
||||
|
||||
@@ -1132,3 +1149,25 @@ function checkEmperior()
|
||||
//연감 월결산
|
||||
LogHistory();
|
||||
}
|
||||
|
||||
function resetInheritanceUser(int $userID){
|
||||
$inheritStor = KVStorage::getStorage(DB::db(), "inheritance_{$userID}");
|
||||
$totalPoint = 0;
|
||||
foreach($inheritStor->getAll() as [$value,]){
|
||||
$totalPoint += $value;
|
||||
}
|
||||
$totalPoint = Util::toInt($totalPoint);
|
||||
$inheritStor->resetValues();
|
||||
$inheritStor->setValue('previous', [$totalPoint, null]);
|
||||
}
|
||||
|
||||
function updateMaxDomesticCritical(General $general, $score){
|
||||
$maxDomesticCritical = $general->getAuxVar('max_domestic_critical')??0;
|
||||
$maxDomesticCritical += $score / 2;
|
||||
$general->setAuxVar('max_domestic_critical', $maxDomesticCritical);
|
||||
|
||||
$oldMaxDomesticCritical = $general->getInheritancePoint('max_domestic_critical');
|
||||
if($maxDomesticCritical > $oldMaxDomesticCritical){
|
||||
$general->setInheritancePoint('max_domestic_critical', $maxDomesticCritical);
|
||||
}
|
||||
}
|
||||
+11
-6
@@ -689,7 +689,8 @@ function setGift($tnmt_type, $tnmt, $phase) {
|
||||
'grp_no'=>$general['grp_no'],
|
||||
'reward'=>$cost,
|
||||
'msg'=>"<span class='ev_highlight'>16강 진출</span>",
|
||||
'logger'=>$logger
|
||||
'logger'=>$logger,
|
||||
'inheritance_point'=>10,
|
||||
];
|
||||
}
|
||||
//8강자 명성 돈
|
||||
@@ -723,6 +724,7 @@ function setGift($tnmt_type, $tnmt, $phase) {
|
||||
//포상 장수 이름, 금액
|
||||
$resultHelper[$generalID]['reward'] += $cost;
|
||||
$resultHelper[$generalID]['msg'] = "<span class='ev_highlight'>4강 진출</span>";
|
||||
General::createGeneralObjFromDB($generalID)->increaseInheritancePoint('tournament', 10);
|
||||
}
|
||||
//결승자 명성 돈
|
||||
$cost = $admin['develcost'] * 6;
|
||||
@@ -739,6 +741,7 @@ function setGift($tnmt_type, $tnmt, $phase) {
|
||||
//포상 장수 이름, 금액
|
||||
$resultHelper[$generalID]['reward'] += $cost;
|
||||
$resultHelper[$generalID]['msg'] = "<span class='ev_highlight'>준우승</span>으";
|
||||
$resultHelper[$generalID]['inheritance_point'] = 50;
|
||||
if($general['lose'] > 0){
|
||||
$runnerUp = $general;
|
||||
}
|
||||
@@ -761,6 +764,7 @@ function setGift($tnmt_type, $tnmt, $phase) {
|
||||
//포상 장수 이름, 금액
|
||||
$resultHelper[$generalID]['reward'] += $cost;
|
||||
$resultHelper[$generalID]['msg'] = "<span class='ev_highlight'>우승</span>으";
|
||||
$resultHelper[$generalID]['inheritance_point'] = 100;
|
||||
$winner = $general;
|
||||
}
|
||||
|
||||
@@ -775,9 +779,6 @@ function setGift($tnmt_type, $tnmt, $phase) {
|
||||
$runnerUpLogger = $resultHelper[$runnerUp['no']]['logger'];
|
||||
$runnerUpLogger->pushGeneralHistoryLog("<C>{$tp}</> 대회에서 준우승");
|
||||
|
||||
|
||||
|
||||
|
||||
$winnerRewardText = number_format($resultHelper[$winner['no']]['reward']);
|
||||
$runnerUpRewardText = number_format($resultHelper[$runnerUp['no']]['reward']);
|
||||
|
||||
@@ -786,12 +787,16 @@ function setGift($tnmt_type, $tnmt, $phase) {
|
||||
|
||||
$winnerLogger->pushGlobalHistoryLog("<C>{$tp}</> 대회에서 <Y>{$winner['name']}</>{$josaYiWinner} <C>우승</>, <Y>{$runnerUp['name']}</>{$josaYiRunnerUp} <C>준우승</>을 차지하여 천하에 이름을 떨칩니다!", ActionLogger::EVENT_YEAR_MONTH);
|
||||
$winnerLogger->pushGlobalHistoryLog("<C>{$tp}</> 대회의 <S>우승자</>에게는 <C>{$winnerRewardText}</>, <S>준우승자</>에겐 <C>{$runnerUpRewardText}</>의 <S>상금</>과 약간의 <S>명성</>이 주어집니다!", ActionLogger::EVENT_YEAR_MONTH);
|
||||
|
||||
foreach($resultHelper as $general){
|
||||
|
||||
$generalObjList = General::createGeneralObjListFromDB(array_keys($resultHelper));
|
||||
|
||||
foreach($resultHelper as $generalID=>$general){
|
||||
$rewardText = number_format($general['reward']);
|
||||
/** @var ActionLogger */
|
||||
$logger = $general['logger'];
|
||||
$logger->pushGeneralActionLog("<C>{$tp}</> 대회의 {$general['msg']}로 <C>{$rewardText}</>의 <S>상금</>, 약간의 <S>명성</> 획득!", ActionLogger::EVENT_PLAIN);
|
||||
//TODO: 토너먼트의 다른 값이 모두 sql에 직접 입력하므로 기반을 바꿔야함.
|
||||
$generalObjList[$generalID]->increaseInheritancePoint('tournament', $general['inheritance_point']);
|
||||
}
|
||||
|
||||
//우승자 번호
|
||||
|
||||
@@ -140,6 +140,7 @@ if(!$v->validate()){
|
||||
'reason'=>'[출병자]'.$v->errorStr()
|
||||
]);
|
||||
}
|
||||
$rawAttacker['owner'] = 0;
|
||||
|
||||
$defenderList = [];
|
||||
foreach($rawDefenderList as $idx=>$rawDefenderGeneral){
|
||||
@@ -152,6 +153,7 @@ foreach($rawDefenderList as $idx=>$rawDefenderGeneral){
|
||||
'reason'=>"[수비자{$idx}]".$v->errorStr()
|
||||
]);
|
||||
}
|
||||
$rawDefenderGeneral['owner'] = 0;
|
||||
|
||||
$defenderList[] = new General($rawDefenderGeneral, extractRankVar($rawDefenderGeneral), $rawDefenderCity, $rawAttackerNation, $year, $month, true);
|
||||
}
|
||||
|
||||
@@ -266,6 +266,8 @@ foreach(Util::range(GameConst::$maxTurn) as $turnIdx){
|
||||
}
|
||||
$db->insert('general_turn', $turnRows);
|
||||
|
||||
resetInheritanceUser($userID);
|
||||
|
||||
$rank_data = [];
|
||||
foreach(array_keys(General::RANK_COLUMN) as $rankColumn){
|
||||
$rank_data[] = [
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -0,0 +1,8 @@
|
||||
/**
|
||||
* @license
|
||||
* Lodash <https://lodash.com/>
|
||||
* Copyright OpenJS Foundation and other contributors <https://openjsf.org/>
|
||||
* Released under MIT license <https://lodash.com/license>
|
||||
* Based on Underscore.js 1.8.3 <http://underscorejs.org/LICENSE>
|
||||
* Copyright Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
|
||||
*/
|
||||
File diff suppressed because one or more lines are too long
+10
-1
@@ -261,6 +261,15 @@ function processWar_NG(
|
||||
|
||||
$attacker->addTrain(1);
|
||||
$defender->addTrain(1);
|
||||
|
||||
$attackerCrewTypeCoef = $attacker->getCrewType()->getAttackCoef($defender->getCrewType()) * $defender->getCrewType()->getDefenceCoef($attacker->getCrewType());
|
||||
$defenderCrewTypeCoef = $defender->getCrewType()->getAttackCoef($attacker->getCrewType()) * $attacker->getCrewType()->getDefenceCoef($defender->getCrewType());
|
||||
if($attackerCrewTypeCoef > $defenderCrewTypeCoef && $attacker instanceof WarUnitGeneral){
|
||||
$attacker->getGeneral()->increaseInheritancePoint('snipe_combat', 1);
|
||||
}
|
||||
if($defenderCrewTypeCoef > $attackerCrewTypeCoef && $defender instanceof WarUnitGeneral){
|
||||
$defender->getGeneral()->increaseInheritancePoint('snipe_combat', 1);
|
||||
}
|
||||
|
||||
$attackerName = $attacker->getName();
|
||||
$attackerCrewTypeName = $attacker->getCrewTypeName();
|
||||
@@ -522,7 +531,7 @@ function ConquerCity(array $admin, General $general, array $city) {
|
||||
|
||||
$lord = new General($db->queryFirstRow(
|
||||
'SELECT %l FROM general WHERE nation = %i AND officer_level = %i LIMIT 1',
|
||||
Util::formatListOfBackticks(General::mergeQueryColumn(['npc', 'gold', 'rice', 'experience', 'explevel', 'dedication', 'dedlevel', 'aux'], 1)[0]),
|
||||
Util::formatListOfBackticks(General::mergeQueryColumn(['npc', 'gold', 'rice', 'experience', 'explevel', 'belong', 'dedication', 'dedlevel', 'aux'], 1)[0]),
|
||||
$defenderNationID,
|
||||
12
|
||||
), null, $city, $loseNation, $year, $month, false);
|
||||
|
||||
@@ -28,6 +28,7 @@ class AutorunNationPolicy {
|
||||
static $NPC몰수 = 'NPC몰수';
|
||||
|
||||
// 군주 행동
|
||||
static $불가침제의 = '불가침제의';
|
||||
static $선전포고 = '선전포고';
|
||||
static $천도 = '천도';
|
||||
|
||||
@@ -35,6 +36,7 @@ class AutorunNationPolicy {
|
||||
|
||||
//실제 행동
|
||||
static public $defaultPriority = [
|
||||
'불가침제의',
|
||||
'선전포고',
|
||||
'천도',
|
||||
|
||||
@@ -106,6 +108,7 @@ class AutorunNationPolicy {
|
||||
public $canNPC포상 = true;
|
||||
public $canNPC몰수 = true;
|
||||
|
||||
public $can불가침제의 = true;
|
||||
public $can선전포고 = true;
|
||||
public $can천도 = true;
|
||||
|
||||
|
||||
@@ -14,7 +14,8 @@ use function sammo\{
|
||||
getDomesticExpLevelBonus,
|
||||
CriticalRatioDomestic,
|
||||
CriticalScoreEx,
|
||||
tryUniqueItemLottery
|
||||
tryUniqueItemLottery,
|
||||
updateMaxDomesticCritical
|
||||
};
|
||||
|
||||
use \sammo\Constraint\Constraint;
|
||||
@@ -93,6 +94,13 @@ class che_기술연구 extends che_상업투자{
|
||||
$exp = $score * 0.7;
|
||||
$ded = $score * 1.0;
|
||||
|
||||
if($pick == 'success'){
|
||||
updateMaxDomesticCritical($general, $score);
|
||||
}
|
||||
else{
|
||||
$general->setAuxVar('max_domestic_critical', 0);
|
||||
}
|
||||
|
||||
$scoreText = number_format($score, 0);
|
||||
|
||||
$josaUl = JosaUtil::pick(static::$actionName, '을');
|
||||
|
||||
@@ -1,21 +1,22 @@
|
||||
<?php
|
||||
|
||||
namespace sammo\Command\General;
|
||||
|
||||
use \sammo\{
|
||||
DB, Util, JosaUtil, TimeUtil, Json,
|
||||
General,
|
||||
ActionLogger,
|
||||
GameConst, GameUnitConst,
|
||||
LastTurn,
|
||||
Command
|
||||
};
|
||||
use \sammo\DB;
|
||||
use \sammo\Util;
|
||||
use \sammo\JosaUtil;
|
||||
use \sammo\TimeUtil;
|
||||
use \sammo\Json;
|
||||
use \sammo\General;
|
||||
use \sammo\ActionLogger;
|
||||
use \sammo\GameConst;
|
||||
use \sammo\GameUnitConst;
|
||||
use \sammo\LastTurn;
|
||||
use \sammo\Command;
|
||||
|
||||
|
||||
use function \sammo\{
|
||||
tryUniqueItemLottery,
|
||||
getInvitationList,
|
||||
getNationStaticInfo
|
||||
};
|
||||
use function \sammo\tryUniqueItemLottery;
|
||||
use function \sammo\getInvitationList;
|
||||
use function \sammo\getNationStaticInfo;
|
||||
|
||||
use \sammo\Constraint\Constraint;
|
||||
use \sammo\Constraint\ConstraintHelper;
|
||||
@@ -24,10 +25,12 @@ use sammo\MustNotBeReachedException;
|
||||
|
||||
|
||||
|
||||
class che_랜덤임관 extends Command\GeneralCommand{
|
||||
class che_랜덤임관 extends Command\GeneralCommand
|
||||
{
|
||||
static protected $actionName = '랜덤임관';
|
||||
|
||||
protected function argTest():bool{
|
||||
protected function argTest(): bool
|
||||
{
|
||||
$this->arg = null;
|
||||
return true;
|
||||
|
||||
@@ -71,7 +74,7 @@ class che_랜덤임관 extends Command\GeneralCommand{
|
||||
|
||||
$relYear = $env['year'] - $env['startyear'];
|
||||
|
||||
$this->fullConditionConstraints=[
|
||||
$this->fullConditionConstraints = [
|
||||
ConstraintHelper::BeNeutral(),
|
||||
ConstraintHelper::AllowJoinAction(),
|
||||
];
|
||||
@@ -83,28 +86,34 @@ class che_랜덤임관 extends Command\GeneralCommand{
|
||||
*/
|
||||
}
|
||||
|
||||
public function getCommandDetailTitle():string{
|
||||
public function getCommandDetailTitle(): string
|
||||
{
|
||||
return '무작위 국가로 임관';
|
||||
}
|
||||
|
||||
public function getBrief():string{
|
||||
public function getBrief(): string
|
||||
{
|
||||
return '무작위 국가로 임관';
|
||||
}
|
||||
|
||||
public function getCost():array{
|
||||
public function getCost(): array
|
||||
{
|
||||
return [0, 0];
|
||||
}
|
||||
|
||||
public function getPreReqTurn():int{
|
||||
|
||||
public function getPreReqTurn(): int
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
public function getPostReqTurn():int{
|
||||
public function getPostReqTurn(): int
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
public function run():bool{
|
||||
if(!$this->hasFullConditionMet()){
|
||||
public function run(): bool
|
||||
{
|
||||
if (!$this->hasFullConditionMet()) {
|
||||
throw new \RuntimeException('불가능한 커맨드를 강제로 실행 시도');
|
||||
}
|
||||
|
||||
@@ -126,108 +135,107 @@ class che_랜덤임관 extends Command\GeneralCommand{
|
||||
$destNation = null;
|
||||
|
||||
if ($general->getNPCType() >= 2 && !$env['fiction'] && 1000 <= $env['scenario'] && $env['scenario'] < 2000) {
|
||||
if($notIn){
|
||||
if ($notIn) {
|
||||
$nations = $db->query(
|
||||
'SELECT nation.`name` as `name`,nation.nation as nation,scout,gennum,`affinity` FROM nation join general on general.nation = nation.nation and general.officer_level = 12 WHERE scout=0 and gennum<%i and nation.nation not in %li',
|
||||
$relYear<3?GameConst::$initialNationGenLimit:GameConst::$defaultMaxGeneral,
|
||||
$relYear < 3 ? GameConst::$initialNationGenLimit : GameConst::$defaultMaxGeneral,
|
||||
$notIn
|
||||
);
|
||||
}
|
||||
else{
|
||||
} else {
|
||||
$nations = $db->query(
|
||||
'SELECT nation.`name` as `name`,nation.nation as nation,scout,gennum,`affinity` FROM nation join general on general.nation = nation.nation and general.officer_level = 12 WHERE scout=0 and gennum<%i',
|
||||
$relYear<3?GameConst::$initialNationGenLimit:GameConst::$defaultMaxGeneral
|
||||
$relYear < 3 ? GameConst::$initialNationGenLimit : GameConst::$defaultMaxGeneral
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
shuffle($nations);
|
||||
|
||||
$allGen = Util::arraySum($nations, 'gennum');
|
||||
|
||||
$maxScore = 1<<30;
|
||||
|
||||
$maxScore = 1 << 30;
|
||||
|
||||
$affinity = $general->getVar('affinity');
|
||||
|
||||
foreach($nations as $testNation){
|
||||
|
||||
foreach ($nations as $testNation) {
|
||||
$affinity = abs($affinity - $testNation['affinity']);
|
||||
$affinity = min($affinity, abs($affinity - 150));
|
||||
|
||||
$score = log($affinity + 1, 2);//0~
|
||||
|
||||
|
||||
$score = log($affinity + 1, 2); //0~
|
||||
|
||||
//쉐킷쉐킷
|
||||
$score += Util::randF();
|
||||
|
||||
$score += sqrt($testNation['gennum']/$allGen);
|
||||
|
||||
if($score < $maxScore){
|
||||
|
||||
$score += sqrt($testNation['gennum'] / $allGen);
|
||||
|
||||
if ($score < $maxScore) {
|
||||
$maxScore = $score;
|
||||
$destNation = $testNation;
|
||||
}
|
||||
}
|
||||
}
|
||||
else{
|
||||
} else {
|
||||
$onlyRandom = $env['join_mode'] == 'onlyRandom';
|
||||
$genLimit = GameConst::$defaultMaxGeneral;
|
||||
if($onlyRandom && TimeUtil::IsRangeMonth($env['init_year'], $env['init_month'], 1, $env['year'], $env['month'])){
|
||||
if ($onlyRandom && TimeUtil::IsRangeMonth($env['init_year'], $env['init_month'], 1, $env['year'], $env['month'])) {
|
||||
$genLimit = GameConst::$initialNationGenLimitForRandInit;
|
||||
}
|
||||
else if($relYear < 3){
|
||||
} else if ($relYear < 3) {
|
||||
$genLimit = GameConst::$initialNationGenLimit;
|
||||
}
|
||||
|
||||
$generalsCnt = [];
|
||||
if($notIn){
|
||||
if ($notIn) {
|
||||
$rawGeneralsCnt = $db->query(
|
||||
'SELECT general.nation as nation, nation.gennum, nation.name, npc, count(*) as cnt FROM general JOIN nation ON general.nation = nation.nation WHERE npc < 4 AND nation.gennum < %i AND nation.scout=0 AND nation.nation NOT IN %li GROUP BY general.nation, general.npc',
|
||||
'SELECT general.nation as nation, nation.gennum, nation.name, npc, count(*) as cnt FROM general JOIN nation ON general.nation = nation.nation WHERE npc != 9 AND nation.gennum < %i AND nation.scout=0 AND nation.nation NOT IN %li GROUP BY general.nation, general.npc',
|
||||
$genLimit,
|
||||
$notIn
|
||||
);
|
||||
}
|
||||
else{
|
||||
} else {
|
||||
$rawGeneralsCnt = $db->query(
|
||||
'SELECT general.nation as nation, nation.gennum, nation.name, npc, count(*) as cnt FROM general JOIN nation ON general.nation = nation.nation WHERE npc < 4 AND nation.gennum < %i AND nation.scout=0 GROUP BY general.nation, general.npc',
|
||||
'SELECT general.nation as nation, nation.gennum, nation.name, npc, count(*) as cnt FROM general JOIN nation ON general.nation = nation.nation WHERE npc != 9 AND nation.gennum < %i AND nation.scout=0 GROUP BY general.nation, general.npc',
|
||||
$genLimit
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
foreach($rawGeneralsCnt as $nation){
|
||||
|
||||
foreach ($rawGeneralsCnt as $nation) {
|
||||
$nationID = $nation['nation'];
|
||||
if(!\key_exists($nationID, $generalsCnt)){
|
||||
if (!\key_exists($nationID, $generalsCnt)) {
|
||||
$generalsCnt[$nationID] = [
|
||||
'nation'=>$nationID,
|
||||
'gennum'=>$nation['gennum'],
|
||||
'name'=>$nation['name'],
|
||||
'cnt'=>0,
|
||||
'nation' => $nationID,
|
||||
'gennum' => $nation['gennum'],
|
||||
'name' => $nation['name'],
|
||||
'cnt' => 0,
|
||||
];
|
||||
$generalsCnt[$nationID]['cnt'] = 0;
|
||||
}
|
||||
|
||||
if($nation['npc'] <= 2){
|
||||
|
||||
if ($nation['npc'] <= 2) {
|
||||
$calcCnt = $nation['cnt'];
|
||||
}
|
||||
else{
|
||||
} else {
|
||||
$calcCnt = $nation['cnt'] / 2;
|
||||
}
|
||||
|
||||
if ($general->getNPCType() < 2 && Util::starts_with($nation['name'], 'ⓤ')) {
|
||||
$calcCnt *= 100;
|
||||
}
|
||||
|
||||
$generalsCnt[$nationID]['cnt'] += $calcCnt;
|
||||
}
|
||||
|
||||
$randVals = [];
|
||||
foreach($generalsCnt as $testNation){
|
||||
$randVals[] = [$testNation, 1/$testNation['cnt']];
|
||||
foreach ($generalsCnt as $testNation) {
|
||||
$randVals[] = [$testNation, 1 / $testNation['cnt']];
|
||||
}
|
||||
|
||||
if($randVals){
|
||||
if ($randVals) {
|
||||
$destNation = Util::choiceRandomUsingWeightPair($randVals);
|
||||
}
|
||||
}
|
||||
|
||||
$logger = $general->getLogger();
|
||||
|
||||
if(!$destNation){
|
||||
if (!$destNation) {
|
||||
//임관 가능한 국가가 없다!
|
||||
$logger->pushGeneralActionLog("임관 가능한 국가가 없습니다. <1>$date</>");
|
||||
$logger->pushGeneralActionLog("임관 가능한 국가가 없습니다. <1>$date</>");
|
||||
$this->alternative = new che_요양($general, $this->env, null);
|
||||
return false;
|
||||
}
|
||||
@@ -236,7 +244,7 @@ class che_랜덤임관 extends Command\GeneralCommand{
|
||||
$destNationID = $destNation['nation'];
|
||||
$destNationName = $destNation['name'];
|
||||
|
||||
|
||||
|
||||
|
||||
$talkList = [
|
||||
'어쩌다 보니',
|
||||
@@ -257,10 +265,9 @@ class che_랜덤임관 extends Command\GeneralCommand{
|
||||
$logger->pushGeneralHistoryLog("<D><b>{$destNationName}</b></>에 랜덤 임관");
|
||||
$logger->pushGlobalActionLog("<Y>{$generalName}</>{$josaYi} {$randomTalk} <D><b>{$destNationName}</b></>에 <S>임관</>했습니다.");
|
||||
|
||||
if($gennum < GameConst::$initialNationGenLimit) {
|
||||
if ($gennum < GameConst::$initialNationGenLimit) {
|
||||
$exp = 700;
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
$exp = 100;
|
||||
}
|
||||
|
||||
@@ -268,22 +275,21 @@ class che_랜덤임관 extends Command\GeneralCommand{
|
||||
$general->setVar('officer_level', 1);
|
||||
$general->setVar('officer_city', 0);
|
||||
$general->setVar('belong', 1);
|
||||
|
||||
if($this->destGeneralObj !== null){
|
||||
|
||||
if ($this->destGeneralObj !== null) {
|
||||
$general->setVar('city', $this->destGeneralObj->getCityID());
|
||||
}
|
||||
else{
|
||||
} else {
|
||||
$targetCityID = $db->queryFirstField('SELECT city FROM general WHERE nation = %i AND officer_level=12', $destNationID);
|
||||
$general->setVar('city', $targetCityID);
|
||||
}
|
||||
|
||||
$db->update('nation', [
|
||||
'gennum'=>$db->sqleval('gennum + 1')
|
||||
'gennum' => $db->sqleval('gennum + 1')
|
||||
], 'nation=%i', $destNationID);
|
||||
|
||||
$relYear = $env['year'] - $env['startyear'];
|
||||
if($general->getNPCType() == 1 || $relYear >= 3){
|
||||
$joinedNations = $general->getAuxVar('joinedNations')??[];
|
||||
if ($general->getNPCType() == 1 || $relYear >= 3) {
|
||||
$joinedNations = $general->getAuxVar('joinedNations') ?? [];
|
||||
$joinedNations[] = $destNationID;
|
||||
$general->setAuxVar('joinedNations', $joinedNations);
|
||||
}
|
||||
@@ -296,5 +302,4 @@ class che_랜덤임관 extends Command\GeneralCommand{
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,7 +15,8 @@ use function \sammo\{
|
||||
getDomesticExpLevelBonus,
|
||||
CriticalRatioDomestic,
|
||||
CriticalScoreEx,
|
||||
tryUniqueItemLottery
|
||||
tryUniqueItemLottery,
|
||||
updateMaxDomesticCritical
|
||||
};
|
||||
|
||||
use \sammo\Constraint\Constraint;
|
||||
@@ -165,6 +166,13 @@ class che_상업투자 extends Command\GeneralCommand{
|
||||
$exp = $score * 0.7;
|
||||
$ded = $score * 1.0;
|
||||
|
||||
if($pick == 'success'){
|
||||
updateMaxDomesticCritical($general, $score);
|
||||
}
|
||||
else{
|
||||
$general->setAuxVar('max_domestic_critical', 0);
|
||||
}
|
||||
|
||||
$scoreText = number_format($score, 0);
|
||||
|
||||
$josaUl = JosaUtil::pick(static::$actionName, '을');
|
||||
@@ -203,6 +211,4 @@ class che_상업투자 extends Command\GeneralCommand{
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -202,6 +202,8 @@ class che_임관 extends Command\GeneralCommand{
|
||||
$nationList[$nationID]['scoutmsg'] = $scoutMsg;
|
||||
}
|
||||
|
||||
$hiddenItems = [];
|
||||
|
||||
foreach($nationList as &$nation){
|
||||
if($env['year'] < $env['startyear']+3 && $nation['gennum'] >= GameConst::$initialNationGenLimit){
|
||||
$nation['availableJoin'] = false;
|
||||
@@ -217,7 +219,9 @@ class che_임관 extends Command\GeneralCommand{
|
||||
$nation['availableJoin'] = false;
|
||||
}
|
||||
|
||||
|
||||
if(Util::starts_with($nation['name'], 'ⓤ')){
|
||||
$hiddenItems[$nation['nation']] = $nation['nation'];
|
||||
}
|
||||
}
|
||||
unset($nation);
|
||||
ob_start();
|
||||
@@ -228,6 +232,7 @@ class che_임관 extends Command\GeneralCommand{
|
||||
임관할 국가를 목록에서 선택하세요.<br>
|
||||
<select class='formInput' name="destNationID" id="destNationID" size='1' style='color:white;background-color:black;'>
|
||||
<?php foreach($nationList as $nation): ?>
|
||||
<?php if(key_exists($nation['nation'], $hiddenItems)){ continue; } ?>
|
||||
<option
|
||||
value='<?=$nation['nation']?>'
|
||||
style='<?=$nation['availableJoin']?'':'background-color:red;'?>'
|
||||
|
||||
@@ -209,7 +209,10 @@ class che_장수대상임관 extends Command\GeneralCommand{
|
||||
$nationList[$nationID]['scoutmsg'] = $scoutMsg;
|
||||
}
|
||||
|
||||
$hiddenItems = [];
|
||||
|
||||
foreach($nationList as &$nation){
|
||||
$nation['hideen'] = false;
|
||||
if($env['year'] < $env['startyear']+3 && $nation['gennum'] >= GameConst::$initialNationGenLimit){
|
||||
$nation['availableJoin'] = false;
|
||||
}
|
||||
@@ -224,7 +227,9 @@ class che_장수대상임관 extends Command\GeneralCommand{
|
||||
$nation['availableJoin'] = false;
|
||||
}
|
||||
|
||||
|
||||
if(Util::starts_with($nation['name'], 'ⓤ')){
|
||||
$hiddenItems[$nation['nation']] = $nation['nation'];
|
||||
}
|
||||
}
|
||||
unset($nation);
|
||||
ob_start();
|
||||
@@ -235,6 +240,7 @@ class che_장수대상임관 extends Command\GeneralCommand{
|
||||
임관할 국가를 목록에서 선택하세요.<br>
|
||||
<select class='formInput' name="destGeneralID" id="destGeneralID" size='1' style='color:white;background-color:black;'>
|
||||
<?php foreach($generalList as $targetGeneral): ?>
|
||||
<?php if(key_exists($targetGeneral['nation'], $hiddenItems)){ continue; } ?>
|
||||
<option value='<?=$targetGeneral['no']?>'><?=getColoredName($targetGeneral['name'],$targetGeneral['npc'])?>【<?=getNationStaticInfo($targetGeneral['nation'])['name']??'재야'?>】</option>
|
||||
<?php endforeach; ?>
|
||||
</select>
|
||||
|
||||
@@ -15,7 +15,8 @@ use function \sammo\{
|
||||
getDomesticExpLevelBonus,
|
||||
CriticalRatioDomestic,
|
||||
CriticalScoreEx,
|
||||
tryUniqueItemLottery
|
||||
tryUniqueItemLottery,
|
||||
updateMaxDomesticCritical
|
||||
};
|
||||
|
||||
use \sammo\Constraint\Constraint;
|
||||
@@ -150,6 +151,13 @@ class che_정착장려 extends Command\GeneralCommand{
|
||||
$exp = $score * 0.7;
|
||||
$ded = $score * 1.0;
|
||||
|
||||
if($pick == 'success'){
|
||||
updateMaxDomesticCritical($general, $score);
|
||||
}
|
||||
else{
|
||||
$general->setAuxVar('max_domestic_critical', 0);
|
||||
}
|
||||
|
||||
$score *= 10;
|
||||
|
||||
$scoreText = number_format($score, 0);
|
||||
@@ -187,5 +195,5 @@ class che_정착장려 extends Command\GeneralCommand{
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
@@ -15,7 +15,8 @@ use function \sammo\{
|
||||
getDomesticExpLevelBonus,
|
||||
CriticalRatioDomestic,
|
||||
CriticalScoreEx,
|
||||
tryUniqueItemLottery
|
||||
tryUniqueItemLottery,
|
||||
updateMaxDomesticCritical
|
||||
};
|
||||
|
||||
use \sammo\Constraint\Constraint;
|
||||
@@ -150,6 +151,13 @@ class che_주민선정 extends Command\GeneralCommand{
|
||||
$exp = $score * 0.7;
|
||||
$ded = $score * 1.0;
|
||||
|
||||
if($pick == 'success'){
|
||||
updateMaxDomesticCritical($general, $score);
|
||||
}
|
||||
else{
|
||||
$general->setAuxVar('max_domestic_critical', 0);
|
||||
}
|
||||
|
||||
$score /= 10;
|
||||
|
||||
$scoreText = number_format($score, 1);
|
||||
|
||||
@@ -9,16 +9,17 @@ use \sammo\{
|
||||
LastTurn,
|
||||
GameUnitConst,
|
||||
Command,
|
||||
Json,
|
||||
KVStorage,
|
||||
StringUtil
|
||||
};
|
||||
|
||||
use function \sammo\{
|
||||
getDomesticExpLevelBonus,
|
||||
CriticalRatioDomestic,
|
||||
CriticalScoreEx,
|
||||
getAllNationStaticInfo,
|
||||
getNationStaticInfo
|
||||
};
|
||||
use function \sammo\getDomesticExpLevelBonus;
|
||||
use function \sammo\CriticalRatioDomestic;
|
||||
use function \sammo\CriticalScoreEx;
|
||||
use function \sammo\getAllNationStaticInfo;
|
||||
use function \sammo\getNationStaticInfo;
|
||||
|
||||
|
||||
use \sammo\Constraint\Constraint;
|
||||
use \sammo\Constraint\ConstraintHelper;
|
||||
@@ -223,7 +224,10 @@ class che_물자원조 extends Command\NationCommand{
|
||||
$destNationLogger = new ActionLogger(0, $destChiefID, $year, $month);
|
||||
$destNationLogger->pushNationalHistoryLog("<D><b>{$nationName}</b></>{$josaRoSrc}부터 금<C>{$goldAmountText}</> 쌀<C>{$riceAmountText}</>을 지원 받음");
|
||||
|
||||
|
||||
$destNationStor = KVStorage::getStorage(DB::db(), $destNationID, 'nation_env');
|
||||
$destRecvAssist = $destNationStor->getValue('recv_assist')??[];
|
||||
$destRecvAssist["n{$nationID}"] = [$nationID, ($destRecvAssist["n{$nationID}"][1]??0) + $goldAmount + $riceAmount];
|
||||
$destNationStor->setValue('recv_assist', $destRecvAssist);
|
||||
|
||||
$db->update('nation', [
|
||||
'gold'=>$db->sqleval('gold - %i', $goldAmount),
|
||||
|
||||
@@ -2,33 +2,31 @@
|
||||
|
||||
namespace sammo\Command\Nation;
|
||||
|
||||
use\sammo\{
|
||||
DB,
|
||||
Util,
|
||||
JosaUtil,
|
||||
General,
|
||||
DummyGeneral,
|
||||
ActionLogger,
|
||||
GameConst,
|
||||
LastTurn,
|
||||
GameUnitConst,
|
||||
Command,
|
||||
MessageTarget,
|
||||
DiplomaticMessage,
|
||||
Message,
|
||||
};
|
||||
use \sammo\DB;
|
||||
use \sammo\Util;
|
||||
use \sammo\JosaUtil;
|
||||
use \sammo\General;
|
||||
use \sammo\DummyGeneral;
|
||||
use \sammo\ActionLogger;
|
||||
use \sammo\GameConst;
|
||||
use \sammo\LastTurn;
|
||||
use \sammo\GameUnitConst;
|
||||
use \sammo\Command;
|
||||
use \sammo\MessageTarget;
|
||||
use \sammo\DiplomaticMessage;
|
||||
use \sammo\Message;
|
||||
|
||||
use function\sammo\{
|
||||
getDomesticExpLevelBonus,
|
||||
CriticalRatioDomestic,
|
||||
CriticalScoreEx,
|
||||
getAllNationStaticInfo,
|
||||
getNationStaticInfo,
|
||||
GetImageURL
|
||||
};
|
||||
use function \sammo\getDomesticExpLevelBonus;
|
||||
use function \sammo\CriticalRatioDomestic;
|
||||
use function \sammo\CriticalScoreEx;
|
||||
use function \sammo\getAllNationStaticInfo;
|
||||
use function \sammo\getNationStaticInfo;
|
||||
use function \sammo\GetImageUR;
|
||||
|
||||
use \sammo\Constraint\Constraint;
|
||||
use \sammo\Constraint\ConstraintHelper;
|
||||
use sammo\Json;
|
||||
use sammo\KVStorage;
|
||||
|
||||
class che_불가침수락 extends Command\NationCommand
|
||||
{
|
||||
@@ -191,6 +189,13 @@ class che_불가침수락 extends Command\NationCommand
|
||||
$destNationID = $destNation['nation'];
|
||||
$destNationName = $destNation['name'];
|
||||
|
||||
$destNationStor = KVStorage::getStorage(DB::db(), $destNationID, 'nation_env');
|
||||
$destRecvAssist = $destNationStor->getValue('recv_assist')??[];
|
||||
$destRespAssist = $destNationStor->getValue('resp_assist')??[];
|
||||
|
||||
$destRespAssist["n{$nationID}"] = [$nationID, $destRecvAssist["n{$nationID}"][1]??0];
|
||||
$destNationStor->setValue('resp_assist', $destRespAssist);
|
||||
|
||||
$year = $this->arg['year'];
|
||||
$month = $this->arg['month'];
|
||||
|
||||
|
||||
@@ -50,6 +50,11 @@ class AllowJoinDestNation extends Constraint{
|
||||
return false;
|
||||
}
|
||||
|
||||
if($this->general['npc']??2 < 2 && \sammo\Util::starts_with($this->destNation['name'], 'ⓤ')){
|
||||
$this->reason = "유저장은 태수국에 임관할 수 없습니다.";
|
||||
return false;
|
||||
}
|
||||
|
||||
$joinedNations = $this->general['auxVar']['joinedNations']??[];
|
||||
if(in_array($this->destNation['nation'], $joinedNations)){
|
||||
$this->reason = "이미 임관했었던 국가입니다.";
|
||||
|
||||
@@ -0,0 +1,282 @@
|
||||
<?php
|
||||
|
||||
namespace sammo\Event\Action;
|
||||
|
||||
use InvalidArgumentException;
|
||||
use sammo\ActionLogger;
|
||||
use sammo\CityConst;
|
||||
use sammo\DB;
|
||||
use sammo\GameConst;
|
||||
use sammo\Json;
|
||||
use sammo\KVStorage;
|
||||
use sammo\Scenario\GeneralBuilder;
|
||||
use sammo\Scenario\Nation;
|
||||
use sammo\UniqueConst;
|
||||
use sammo\Util;
|
||||
|
||||
use function sammo\GetNationColors;
|
||||
use function sammo\getNationStaticInfo;
|
||||
use function sammo\pickGeneralFromPool;
|
||||
use function sammo\refreshNationStaticInfo;
|
||||
|
||||
class RaiseNPCNation extends \sammo\Event\Action
|
||||
{
|
||||
public function __construct()
|
||||
{
|
||||
}
|
||||
|
||||
const CITY_KEYS = ['pop', 'agri', 'comm', 'secu', 'def', 'wall'];
|
||||
const MIN_DIST_USERNATION = 4;
|
||||
const MIN_DIST_NPCNATION = 2;
|
||||
|
||||
private function calcAvgNationCity(array $cities)
|
||||
{
|
||||
if (count($cities) == 0) {
|
||||
throw new InvalidArgumentException();
|
||||
}
|
||||
|
||||
$targetCities = [];
|
||||
|
||||
foreach ($cities as $city) {
|
||||
if ($city['nation'] == 0) {
|
||||
continue;
|
||||
}
|
||||
$citySum = 0;
|
||||
foreach (static::CITY_KEYS as $key) {
|
||||
if ($key === 'pop') {
|
||||
continue;
|
||||
}
|
||||
$citySum += $city[$key];
|
||||
}
|
||||
$city['sum'] = $citySum;
|
||||
|
||||
$targetCities[] = $city;
|
||||
}
|
||||
|
||||
$cityCnt = count($targetCities);
|
||||
|
||||
if ($cityCnt == 0) {
|
||||
$target = Util::choiceRandom($cities);
|
||||
$randCity = [];
|
||||
foreach (static::CITY_KEYS as $key) {
|
||||
$randCity[$key] = $target["{$key}_max"];
|
||||
}
|
||||
return $randCity;
|
||||
}
|
||||
|
||||
usort($targetCities, function (array $lhs, array $rhs) {
|
||||
return $lhs['sum'] <=> $rhs['sum'];
|
||||
});
|
||||
|
||||
|
||||
//최소, 최대 도시 몇개를 뺀다. 정렬은 신경쓰지 않는다.
|
||||
|
||||
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($baseCity["{$key}_max"], $avgCity[$key]);
|
||||
}
|
||||
|
||||
$pickTypeList = ['무' => 1, '지' => 1];
|
||||
|
||||
$cityID = $baseCity['city'];
|
||||
$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);
|
||||
|
||||
$ruler = (new GeneralBuilder("{$cityName}태수", false, null, $nationID))
|
||||
->setOfficerLevel(12)
|
||||
->setCityID($cityID)
|
||||
->setNPCType(6)
|
||||
->setGoldRice(1000, 1000)
|
||||
->fillRandomStat($pickTypeList)
|
||||
->setKillturn(240)
|
||||
->fillRemainSpecAsZero($env);
|
||||
$ruler->build($env);
|
||||
|
||||
$nationObj->addGeneral($ruler);
|
||||
|
||||
$birthYear = $env['year'] - 20;
|
||||
$deadYearMin = $env['year'] + 10;
|
||||
|
||||
foreach (pickGeneralFromPool(DB::db(), 0, $genCnt - 1) as $pickedNPC) {
|
||||
//대충 10년후부터 6년마다 절반?
|
||||
$deadYear = $deadYearMin + Util::toInt(60 * (1 - log(Util::randRange(1, 1024), 2)/10));
|
||||
$newNPC = $pickedNPC->getGeneralBuilder();
|
||||
$newNPC->setNationID($nationID)
|
||||
->setCityID($cityID)
|
||||
->setNPCType(6)
|
||||
->setGoldRice(1000, 1000)
|
||||
->setLifeSpan($birthYear, $deadYear)
|
||||
->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;
|
||||
$lastNationID = max(
|
||||
$db->queryFirstField("SELECT max(`nation`) FROM `nation`"),
|
||||
$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 = [];
|
||||
|
||||
refreshNationStaticInfo();
|
||||
|
||||
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("<L><b>【공지】</b></>공백지에 임의의 국가가 생성되었습니다.");
|
||||
$logger->flush();
|
||||
}
|
||||
|
||||
return [__CLASS__, count($npcCities)];
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,8 @@
|
||||
<?php
|
||||
namespace sammo\Event\Condition;
|
||||
|
||||
use sammo\Event\Condition;
|
||||
|
||||
class Logic extends \sammo\Event\Condition{
|
||||
private $mode = 'and';
|
||||
|
||||
@@ -24,7 +26,9 @@ class Logic extends \sammo\Event\Condition{
|
||||
}
|
||||
|
||||
$this->mode = $mode;
|
||||
$this->conditions = $conditions;
|
||||
$this->conditions = array_map(function($condition){
|
||||
return Condition::build($condition);
|
||||
}, $conditions);
|
||||
}
|
||||
|
||||
public function eval($env=null){
|
||||
|
||||
+207
-3
@@ -50,6 +50,20 @@ class General implements iAction{
|
||||
'occupied'=>1,
|
||||
];
|
||||
|
||||
const INHERITANCE_KEY = [
|
||||
'previous'=>[true, 1, '기존 포인트'],
|
||||
'lived_month'=>[true, 1, '생존'],
|
||||
'max_belong'=>[false, 10, '최대 임관년 수'],
|
||||
'max_domestic_critical'=>[true, 1, '최대 연속 내정 성공'],
|
||||
'snipe_combat'=>[true, 10, '병종 상성 우위 횟수'],
|
||||
'combat'=>[['rank', 'warnum'], 5, '전투 횟수'],
|
||||
'sabotage'=>[['rank', 'firenum'], 20, '계략 성공 횟수'],
|
||||
'unifier'=>[true, 1, '천통 기여'],
|
||||
'dex'=>[false, 0.001, '숙련도'],
|
||||
'tournament'=>[true, 1, '토너먼트'],
|
||||
'betting'=>[false, 10, '베팅 당첨'],
|
||||
];
|
||||
|
||||
const TURNTIME_FULL_MS = -1;
|
||||
const TURNTIME_FULL = 0;
|
||||
const TURNTIME_HMS = 1;
|
||||
@@ -539,6 +553,8 @@ class General implements iAction{
|
||||
|
||||
$generalName = $this->getName();
|
||||
|
||||
$this->mergeTotalInheritancePoint();
|
||||
|
||||
// 군주였으면 유지 이음
|
||||
$officerLevel = $this->getVar('officer_level');
|
||||
if($officerLevel == 12) {
|
||||
@@ -592,6 +608,12 @@ class General implements iAction{
|
||||
|
||||
$generalName = $this->getName();
|
||||
|
||||
$ownerID = $this->getVar('owner');
|
||||
if($ownerID){
|
||||
$this->mergeTotalInheritancePoint();
|
||||
resetInheritanceUser($ownerID);
|
||||
}
|
||||
|
||||
$this->multiplyVarWithLimit('leadership', 0.85, 10);
|
||||
$this->multiplyVarWithLimit('strength', 0.85, 10);
|
||||
$this->multiplyVarWithLimit('intel', 0.85, 10);
|
||||
@@ -919,19 +941,19 @@ class General implements iAction{
|
||||
static public function mergeQueryColumn(?array $reqColumns=null, int $constructMode=2):array{
|
||||
$minimumColumn = ['no', 'name', 'city', 'nation', 'officer_level', 'officer_city'];
|
||||
$defaultEventColumn = [
|
||||
'no', 'name', 'city', 'nation', 'officer_level', 'officer_city',
|
||||
'no', 'name', 'owner', 'city', 'nation', 'officer_level', 'officer_city',
|
||||
'special', 'special2', 'personal',
|
||||
'horse', 'weapon', 'book', 'item', 'last_turn'
|
||||
];
|
||||
$fullColumn = [
|
||||
'no', 'name', 'owner_name', 'picture', 'imgsvr', 'nation', 'city', 'troop', 'injury', 'affinity',
|
||||
'no', 'name', 'owner', 'owner_name', 'picture', 'imgsvr', 'nation', 'city', 'troop', 'injury', 'affinity',
|
||||
'leadership', 'leadership_exp', 'strength', 'strength_exp', 'intel', 'intel_exp', 'weapon', 'book', 'horse', 'item',
|
||||
'experience', 'dedication', 'officer_level', 'officer_city', 'gold', 'rice', 'crew', 'crewtype', 'train', 'atmos', 'turntime',
|
||||
'makelimit', 'killturn', 'block', 'dedlevel', 'explevel', 'age', 'startage', 'belong',
|
||||
'personal', 'special', 'special2', 'defence_train', 'tnmt', 'npc', 'npc_org', 'deadyear', 'npcmsg',
|
||||
'dex1', 'dex2', 'dex3', 'dex4', 'dex5', 'betray',
|
||||
'recent_war', 'last_turn', 'myset',
|
||||
'specage', 'specage2', 'con', 'connect', 'owner', 'aux', 'lastrefresh',
|
||||
'specage', 'specage2', 'con', 'connect', 'aux', 'lastrefresh',
|
||||
];
|
||||
|
||||
if($reqColumns === null){
|
||||
@@ -1141,4 +1163,186 @@ class General implements iAction{
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int|float
|
||||
*/
|
||||
public function getInheritancePoint(string $key, &$aux=null, bool $forceCalc=false){
|
||||
$inheritType = static::INHERITANCE_KEY[$key]??null;
|
||||
if($inheritType === null){
|
||||
throw new \OutOfRangeException("{$key}는 유산 타입이 아님");
|
||||
}
|
||||
|
||||
$ownerID = $this->getVar('owner');
|
||||
if(!$ownerID){
|
||||
return 0;
|
||||
}
|
||||
|
||||
if($this->getVar('npc') != 0){
|
||||
return 0;
|
||||
}
|
||||
|
||||
[$storeType, $multiplier, ] = $inheritType;
|
||||
|
||||
$gameStor = KVStorage::getStorage(DB::db(), 'game_env');
|
||||
if($storeType === true || ($gameStor->isunited != 0 && !$forceCalc)){
|
||||
$inheritStor = KVStorage::getStorage(DB::db(), "inheritance_{$ownerID}");
|
||||
[$value, $aux] = $inheritStor->getValue($key);
|
||||
return $value;
|
||||
}
|
||||
|
||||
if(is_array($storeType)){
|
||||
[$storSubType, $storSubKey] = $storeType;
|
||||
if($storSubType === 'rank'){
|
||||
return $this->getRankVar($storSubKey) * $multiplier;
|
||||
}
|
||||
if($storSubType === 'raw'){
|
||||
return $this->getVar($storSubKey) * $multiplier;
|
||||
}
|
||||
if($storSubType === 'aux'){
|
||||
return ($this->getAuxVar($storSubKey)??0) * $multiplier;
|
||||
}
|
||||
throw new \InvalidArgumentException("{$storSubType}은 참조 할 수 없는 유산 세부키임");
|
||||
}
|
||||
|
||||
if($storeType !== false){
|
||||
throw new \InvalidArgumentException("{$storeType}은 올바르지 않은 유산 키임");
|
||||
}
|
||||
|
||||
$extractFn = function(){ return [0, null];};
|
||||
switch($key){
|
||||
case 'dex':
|
||||
$extractFn = function() use ($multiplier){
|
||||
$totalDex = 0;
|
||||
foreach(array_keys(GameUnitConst::allType()) as $armType){
|
||||
$totalDex += $this->getVar("dex{$armType}");
|
||||
}
|
||||
return [$totalDex * $multiplier, null];
|
||||
};
|
||||
break;
|
||||
case 'betting':
|
||||
$extractFn = function() use ($multiplier){
|
||||
$betWin = $this->getRankVar('betwin');
|
||||
$betWinRate = $this->getRankVar('betwingold')/max(1, $this->getRankVar('betgold'));
|
||||
|
||||
return [$betWin * $multiplier * pow($betWinRate, 2), null];
|
||||
};
|
||||
break;
|
||||
case 'max_belong':
|
||||
$extractFn = function() use ($multiplier){
|
||||
$maxBelong = max($this->getVar('belong'), $this->getAuxVar('max_belong')??0);
|
||||
return [$maxBelong * $multiplier, null];
|
||||
};
|
||||
break;
|
||||
default:
|
||||
throw new \InvalidArgumentException("{$key}는 유산 추출기를 보유하고 있지 않음");
|
||||
}
|
||||
|
||||
[$value, $aux] = ($extractFn)();
|
||||
return $value;
|
||||
}
|
||||
|
||||
public function setInheritancePoint(string $key, $value, $aux=null){
|
||||
if(!is_int($value) && !is_float($value)){
|
||||
throw new \InvalidArgumentException("{$value}는 숫자가 아님");
|
||||
}
|
||||
$inheritType = static::INHERITANCE_KEY[$key]??null;
|
||||
if($inheritType === null){
|
||||
throw new \OutOfRangeException("{$key}는 유산 타입이 아님");
|
||||
}
|
||||
|
||||
[$storeType, $multiplier, ] = $inheritType;
|
||||
if($storeType !== true){
|
||||
throw new \InvalidArgumentException("{$key}는 직접 저장형 유산 포인트가 아님");
|
||||
}
|
||||
if($multiplier != 1 && $value != 0){
|
||||
throw new \InvalidArgumentException("{$key}는 1:1 유산 포인트가 아님");
|
||||
}
|
||||
|
||||
$ownerID = $this->getVar('owner');
|
||||
if(!$ownerID){
|
||||
return;
|
||||
}
|
||||
|
||||
if($this->getVar('npc') != 0){
|
||||
return;
|
||||
}
|
||||
|
||||
$gameStor = KVStorage::getStorage(DB::db(), 'game_env');
|
||||
if($gameStor->isunited != 0){
|
||||
return;
|
||||
}
|
||||
|
||||
$inheritStor = KVStorage::getStorage(DB::db(), "inheritance_{$ownerID}");
|
||||
$inheritStor->setValue($key, [$value, $aux]);
|
||||
}
|
||||
|
||||
public function increaseInheritancePoint(string $key, $value, $aux=null){
|
||||
if(!is_int($value) && !is_float($value)){
|
||||
throw new \InvalidArgumentException("{$value}는 숫자가 아님");
|
||||
}
|
||||
|
||||
$inheritType = static::INHERITANCE_KEY[$key]??null;
|
||||
if($inheritType === null){
|
||||
throw new \OutOfRangeException("{$key}는 유산 타입이 아님");
|
||||
}
|
||||
|
||||
[$storeType, $multiplier, ] = $inheritType;
|
||||
if($storeType !== true){
|
||||
throw new \InvalidArgumentException("{$key}는 직접 저장형 유산 포인트가 아님");
|
||||
}
|
||||
|
||||
$ownerID = $this->getVar('owner');
|
||||
if(!$ownerID){
|
||||
return;
|
||||
}
|
||||
|
||||
if($this->getVar('npc') != 0){
|
||||
return;
|
||||
}
|
||||
|
||||
$gameStor = KVStorage::getStorage(DB::db(), 'game_env');
|
||||
if($gameStor->isunited != 0){
|
||||
return;
|
||||
}
|
||||
|
||||
$inheritStor = KVStorage::getStorage(DB::db(), "inheritance_{$ownerID}");
|
||||
[$oldValue, $oldAux] = $inheritStor->getValue($key)??[0, null];
|
||||
|
||||
if($oldAux !== $aux){
|
||||
$oldValue = 0;
|
||||
}
|
||||
|
||||
$newValue = $oldValue + $value * $multiplier;
|
||||
$inheritStor->setValue($key, [$newValue, $aux]);
|
||||
}
|
||||
|
||||
public function mergeTotalInheritancePoint(){
|
||||
$ownerID = $this->getVar('owner');
|
||||
if(!$ownerID){
|
||||
return;
|
||||
}
|
||||
|
||||
if($this->getVar('npc') != 0){
|
||||
return;
|
||||
}
|
||||
|
||||
$inheritStor = KVStorage::getStorage(DB::db(), "inheritance_{$ownerID}");
|
||||
$inheritStor->cacheAll();
|
||||
foreach(static::INHERITANCE_KEY as $key=>[$storType, ,]){
|
||||
$aux = null;
|
||||
$point = $this->getInheritancePoint($key, $aux, true);
|
||||
if($storType === true){
|
||||
continue;
|
||||
}
|
||||
$inheritStor->setValue($key, [$point, $aux]);
|
||||
}
|
||||
|
||||
$oldInheritStor = KVStorage::getStorage(DB::db(), "inheritance_result");
|
||||
$gameStor = KVStorage::getStorage(DB::db(), 'game_env');
|
||||
$serverID = UniqueConst::$serverID;
|
||||
$year = $gameStor->year;
|
||||
$month = $gameStor->month;
|
||||
$oldInheritStor->setValue("{$serverID}_{$ownerID}_{$this->getID()}_{$year}_{$month}", $inheritStor->getAll(true));
|
||||
}
|
||||
}
|
||||
+86
-2
@@ -1712,6 +1712,88 @@ class GeneralAI
|
||||
return $cmd;
|
||||
}
|
||||
|
||||
// 군주 행동
|
||||
protected function do불가침제의(LastTurn $lastTurn): ?NationCommand
|
||||
{
|
||||
$general = $this->general;
|
||||
|
||||
if($general->getVar('officer_level') < 12){
|
||||
return null;
|
||||
}
|
||||
|
||||
$nation = $this->nation;
|
||||
$nationID = $nation['nation'];
|
||||
|
||||
$nationStor = KVStorage::getStorage(DB::db(), $nationID, 'nation_env');
|
||||
$recvAssist = $nationStor->getValue('recv_assist')??[];
|
||||
$respAssist = $nationStor->getValue('resp_assist')??[];
|
||||
$respAssistTry = $nationStor->getValue('resp_assist_try')??[];
|
||||
|
||||
$yearMonth = Util::joinYearMonth($this->env['year'], $this->env['month']);
|
||||
|
||||
$candidateList = [];
|
||||
foreach($recvAssist as [$candNationID, $amount]){
|
||||
$amount -= $respAssist["n{$candNationID}"][1]??0;
|
||||
if($amount <= 0){
|
||||
continue;
|
||||
}
|
||||
if(key_exists($candNationID, $this->warTargetNation)){
|
||||
continue;
|
||||
}
|
||||
if(($respAssistTry["n{$candNationID}"][1]??0) >= $yearMonth - 8){
|
||||
continue;
|
||||
}
|
||||
$candidateList[$candNationID] = $amount;
|
||||
}
|
||||
|
||||
if(!$candidateList){
|
||||
return null;
|
||||
}
|
||||
|
||||
$cityList = $this->supplyCities;
|
||||
|
||||
if (!$cityList) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$goldIncome = getGoldIncome($nation['nation'], $nation['level'], 15, $nation['capital'], $nation['type'], $cityList);
|
||||
$riceIncome = getRiceIncome($nation['nation'], $nation['level'], 15, $nation['capital'], $nation['type'], $cityList);
|
||||
$wallIncome = getWallIncome($nation['nation'], $nation['level'], 15, $nation['capital'], $nation['type'], $cityList);
|
||||
$income = $goldIncome + $riceIncome + $wallIncome;
|
||||
|
||||
arsort($candidateList);
|
||||
$destNationID = null;
|
||||
$diplomatMonth = 0;
|
||||
foreach($candidateList as $candNationID => $amount){
|
||||
if($amount * 4 < $income){
|
||||
break;
|
||||
}
|
||||
$destNationID = $candNationID;
|
||||
$diplomatMonth = 24 * $amount / $income;
|
||||
break;
|
||||
}
|
||||
|
||||
if($destNationID === null){
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
[$targetYear, $targetMonth] = Util::parseYearMonth($yearMonth + $diplomatMonth);
|
||||
|
||||
$cmd = buildNationCommandClass('che_불가침제의', $this->general, $this->env, $lastTurn, [
|
||||
'destNationID' => $destNationID,
|
||||
'year' => $targetYear,
|
||||
'month' => $targetMonth,
|
||||
]);
|
||||
if(!$cmd->hasFullConditionMet()){
|
||||
return null;
|
||||
}
|
||||
|
||||
$respAssistTry["n{$destNationID}"] = [$destNationID, $yearMonth];
|
||||
$nationStor->setValue('resp_assist_try', $respAssistTry);
|
||||
|
||||
return $cmd;
|
||||
}
|
||||
|
||||
// 군주 행동
|
||||
protected function do선전포고(LastTurn $lastTurn): ?NationCommand
|
||||
@@ -3067,6 +3149,9 @@ class GeneralAI
|
||||
if($general->getVar('makelimit')){
|
||||
return null;
|
||||
}
|
||||
if($general->getNPCType() > 2){
|
||||
return null;
|
||||
}
|
||||
if(!$this->generalPolicy->can건국){
|
||||
return null;
|
||||
}
|
||||
@@ -3167,8 +3252,7 @@ class GeneralAI
|
||||
return null;
|
||||
}
|
||||
|
||||
if (Util::randBool(pow(1 / $nationCnt / pow($notFullNationCnt, 3), 1 / 4))) {
|
||||
//국가가 1개일 경우에는 '임관하지 않음'
|
||||
if (Util::randBool(pow(1 / ($nationCnt + 1) / pow($notFullNationCnt, 3), 1 / 4))) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -76,7 +76,10 @@ class Nation{
|
||||
$capital = 0;
|
||||
}
|
||||
|
||||
if(strpos($this->type, '_') === FALSE){
|
||||
if($this->type === null){
|
||||
$type = Util::choiceRandom(GameConst::$availableNationType);
|
||||
}
|
||||
else if(strpos($this->type, '_') === FALSE){
|
||||
$type = 'che_'.$this->type;
|
||||
}
|
||||
else{
|
||||
|
||||
@@ -257,6 +257,8 @@ class TurnExecutionHelper
|
||||
$autorunMode = false;
|
||||
$ai = null;
|
||||
|
||||
$general->increaseInheritancePoint('lived_month', 1);
|
||||
|
||||
$turnObj->preprocessCommand($env);
|
||||
$generalCommandObj = $general->getReservedTurn(0, $env);
|
||||
|
||||
|
||||
@@ -5,5 +5,17 @@
|
||||
],
|
||||
"const": {
|
||||
"joinRuinedNPCProp":0
|
||||
}
|
||||
},
|
||||
"events":[
|
||||
[
|
||||
["or", ["Date", "==", null, 12], ["Date", "==", null, 6]],
|
||||
["CreateManyNPC", 30],
|
||||
["DeleteEvent"]
|
||||
],
|
||||
[
|
||||
["Date", "==", 181, 1],
|
||||
["RaiseNPCNation"],
|
||||
["DeleteEvent"]
|
||||
]
|
||||
]
|
||||
}
|
||||
@@ -8,5 +8,17 @@
|
||||
],
|
||||
"const": {
|
||||
"joinRuinedNPCProp":0
|
||||
}
|
||||
},
|
||||
"events":[
|
||||
[
|
||||
["or", ["Date", "==", null, 12], ["Date", "==", null, 6]],
|
||||
["CreateManyNPC", 30],
|
||||
["DeleteEvent"]
|
||||
],
|
||||
[
|
||||
["Date", "==", 181, 1],
|
||||
["RaiseNPCNation"],
|
||||
["DeleteEvent"]
|
||||
]
|
||||
]
|
||||
}
|
||||
@@ -15,9 +15,14 @@
|
||||
},
|
||||
"events":[
|
||||
[
|
||||
["Date", "==", null, 12],
|
||||
["or", ["Date", "==", null, 12], ["Date", "==", null, 6]],
|
||||
["CreateManyNPC", 30],
|
||||
["DeleteEvent"]
|
||||
],
|
||||
[
|
||||
["Date", "==", 181, 1],
|
||||
["RaiseNPCNation"],
|
||||
["DeleteEvent"]
|
||||
]
|
||||
]
|
||||
}
|
||||
@@ -16,7 +16,7 @@
|
||||
<a href='b_diplomacy.php'><button type="button" class='commandButton' style='background-color:<?=$bgColor?>;color:<?=$fgColor?>;'>중원 정보</button></a>
|
||||
<a href='b_currentCity.php'><button type="button" class='commandButton' style='background-color:<?=$bgColor?>;color:<?=$fgColor?>;'>현재 도시</button></a>
|
||||
<a href='b_battleCenter.php' target='_blank'><button type="button" class='commandButton' <?=$showSecret?'':'disabled'?> style='background-color:<?=$bgColor?>;color:<?=$fgColor?>;'>감 찰 부</button></a>
|
||||
<button type="button" style="visibility:hidden;" class='commandButton'>빈칸</button>
|
||||
<a href='b_inheritPoint.php'><button type="button" class='commandButton' style='background-color:<?=$bgColor?>;color:<?=$fgColor?>;'>유산 관리</button></a>
|
||||
<a href='b_myPage.php'><button type="button" class='commandButton' style='background-color:<?=$bgColor?>;color:<?=$fgColor?>;'>내 정보&설정</button></a>
|
||||
<a href='b_auction.php' target='_blank'><button type="button" class='commandButton' style='background-color:<?=$bgColor?>;color:<?=$fgColor?>;'>거 래 장</button></a>
|
||||
<a href='b_betting.php' target='_blank'><button type="button" class='commandButton' style='background-color:<?=$bgColor?>;color:<?=$fgColor?>;'>베 팅 장</button></a>
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
import { sum } from "lodash";
|
||||
import { unwrap } from "./util";
|
||||
declare global {
|
||||
interface Window {
|
||||
formStart: ()=>void;
|
||||
items: {[name: string]:number};
|
||||
helpText: {[name: string]:string};
|
||||
}
|
||||
}
|
||||
|
||||
export {}
|
||||
|
||||
function formStart() {
|
||||
|
||||
const dSum = unwrap(document.querySelector('#inherit_sum_value')) as HTMLInputElement ;
|
||||
const dOld = unwrap(document.querySelector('#inherit_previous_value')) as HTMLInputElement;
|
||||
const dNew = unwrap(document.querySelector('#inherit_new_value')) as HTMLInputElement;
|
||||
|
||||
const sumPoint = Math.floor(sum(Object.values(window.items)));
|
||||
const oldPoint = Math.floor(window.items['previous']);
|
||||
const sumNewPoint = sumPoint - oldPoint;
|
||||
|
||||
dSum.value = sumPoint.toLocaleString();
|
||||
dOld.value = oldPoint.toLocaleString();
|
||||
dNew.value = sumNewPoint.toLocaleString();
|
||||
|
||||
for(const [key, val] of Object.entries(window.items)){
|
||||
const dItem = unwrap(document.querySelector(`#inherit_${key}_value`)) as HTMLInputElement ;
|
||||
dItem.value = Math.floor(val).toLocaleString();
|
||||
}
|
||||
|
||||
for(const [key, text] of Object.entries(window.helpText)){
|
||||
const dText = unwrap(document.querySelector(`#inherit_${key} small.form-text`)) as HTMLElement;
|
||||
dText.innerHTML = text;
|
||||
}
|
||||
}
|
||||
|
||||
window.formStart = formStart;
|
||||
@@ -0,0 +1,35 @@
|
||||
type ErrType<T> = { new(msg?: string): T }
|
||||
type Nullable<T> = T | null | undefined
|
||||
|
||||
export class RuntimeError extends Error {
|
||||
public name = 'RuntimeError';
|
||||
constructor(public message: string = '') {
|
||||
super(message);
|
||||
}
|
||||
toString(): string {
|
||||
if (this.message) {
|
||||
return this.name + ': ' + this.message;
|
||||
}
|
||||
else {
|
||||
return this.name;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export class NotNullExpected extends RuntimeError {
|
||||
public name = 'NotNullExpected';
|
||||
}
|
||||
|
||||
export function unwrap<T>(result: Nullable<T>): T {
|
||||
if (result === null || result === undefined) {
|
||||
throw new NotNullExpected();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
export function unwrap_err<T, ErrT extends Error>(result: Nullable<T>, errType: ErrType<ErrT>, errMsg?: string): T {
|
||||
if (result === null || result === undefined) {
|
||||
throw new errType(errMsg);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
{
|
||||
"name": "hidche_lib",
|
||||
"version": "1.0.0",
|
||||
"description": "",
|
||||
"main": "js/index.js",
|
||||
"scripts": {
|
||||
"test": "echo \"Error: no test specified\" && exit 1",
|
||||
"build": "webpack",
|
||||
"lint": "eslint hwe/ts ts"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "ssh://git@storage.hided.net:2525/devsam/core.git"
|
||||
},
|
||||
"author": "Hide_D",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@types/lodash": "^4.14.172",
|
||||
"lodash": "^4.17.21"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/cli": "^7.14.8",
|
||||
"@babel/core": "^7.15.0",
|
||||
"@babel/preset-env": "^7.15.0",
|
||||
"@babel/preset-typescript": "^7.15.0",
|
||||
"@typescript-eslint/eslint-plugin": "^4.29.1",
|
||||
"@typescript-eslint/parser": "^4.29.1",
|
||||
"babel-loader": "^8.2.2",
|
||||
"babel-plugin-lodash": "^3.3.4",
|
||||
"eslint": "^7.32.0",
|
||||
"pre-commit": "^1.2.2",
|
||||
"typescript": "^4.3.5",
|
||||
"webpack": "^5.49.0",
|
||||
"webpack-cli": "^4.7.2"
|
||||
},
|
||||
"pre-commit": [
|
||||
"lint"
|
||||
]
|
||||
}
|
||||
Vendored
+7
@@ -0,0 +1,7 @@
|
||||
interface Window {
|
||||
pathConfig: {
|
||||
root: string,
|
||||
sharedIcon: string,
|
||||
gameImage: string,
|
||||
}
|
||||
}
|
||||
+35
@@ -0,0 +1,35 @@
|
||||
type ErrType<T> = { new(msg?: string): T }
|
||||
type Nullable<T> = T | null | undefined
|
||||
|
||||
export class RuntimeError extends Error {
|
||||
public name = 'RuntimeError';
|
||||
constructor(public message: string = '') {
|
||||
super(message);
|
||||
}
|
||||
toString(): string {
|
||||
if (this.message) {
|
||||
return this.name + ': ' + this.message;
|
||||
}
|
||||
else {
|
||||
return this.name;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export class NotNullExpected extends RuntimeError {
|
||||
public name = 'NotNullExpected';
|
||||
}
|
||||
|
||||
export function unwrap<T>(result: Nullable<T>): T {
|
||||
if (result === null || result === undefined) {
|
||||
throw new NotNullExpected();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
export function unwrap_err<T, ErrT extends Error>(result: Nullable<T>, errType: ErrType<ErrT>, errMsg?: string): T {
|
||||
if (result === null || result === undefined) {
|
||||
throw new errType(errMsg);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
@@ -0,0 +1,72 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
/* Visit https://aka.ms/tsconfig.json to read more about this file */
|
||||
|
||||
/* Basic Options */
|
||||
// "incremental": true, /* Enable incremental compilation */
|
||||
"target": "esnext", /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019', 'ES2020', 'ES2021', or 'ESNEXT'. */
|
||||
"module": "ESNext", /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', 'es2020', or 'ESNext'. */
|
||||
// "lib": [], /* Specify library files to be included in the compilation. */
|
||||
// "allowJs": true, /* Allow javascript files to be compiled. */
|
||||
// "checkJs": true, /* Report errors in .js files. */
|
||||
// "jsx": "preserve", /* Specify JSX code generation: 'preserve', 'react-native', 'react', 'react-jsx' or 'react-jsxdev'. */
|
||||
// "declaration": true, /* Generates corresponding '.d.ts' file. */
|
||||
// "declarationMap": true, /* Generates a sourcemap for each corresponding '.d.ts' file. */
|
||||
// "sourceMap": true, /* Generates corresponding '.map' file. */
|
||||
// "outFile": "./", /* Concatenate and emit output to single file. */
|
||||
// "outDir": "../js", /* Redirect output structure to the directory. */
|
||||
// "rootDir": "./", /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */
|
||||
// "composite": true, /* Enable project compilation */
|
||||
// "tsBuildInfoFile": "./", /* Specify file to store incremental compilation information */
|
||||
// "removeComments": true, /* Do not emit comments to output. */
|
||||
"noEmit": true, /* Do not emit outputs. */
|
||||
// "importHelpers": true, /* Import emit helpers from 'tslib'. */
|
||||
// "downlevelIteration": true, /* Provide full support for iterables in 'for-of', spread, and destructuring when targeting 'ES5' or 'ES3'. */
|
||||
"isolatedModules": true, /* Transpile each file as a separate module (similar to 'ts.transpileModule'). */
|
||||
|
||||
/* Strict Type-Checking Options */
|
||||
"strict": true, /* Enable all strict type-checking options. */
|
||||
// "noImplicitAny": true, /* Raise error on expressions and declarations with an implied 'any' type. */
|
||||
// "strictNullChecks": true, /* Enable strict null checks. */
|
||||
// "strictFunctionTypes": true, /* Enable strict checking of function types. */
|
||||
// "strictBindCallApply": true, /* Enable strict 'bind', 'call', and 'apply' methods on functions. */
|
||||
// "strictPropertyInitialization": true, /* Enable strict checking of property initialization in classes. */
|
||||
// "noImplicitThis": true, /* Raise error on 'this' expressions with an implied 'any' type. */
|
||||
// "alwaysStrict": true, /* Parse in strict mode and emit "use strict" for each source file. */
|
||||
|
||||
/* Additional Checks */
|
||||
// "noUnusedLocals": true, /* Report errors on unused locals. */
|
||||
// "noUnusedParameters": true, /* Report errors on unused parameters. */
|
||||
// "noImplicitReturns": true, /* Report error when not all code paths in function return a value. */
|
||||
// "noFallthroughCasesInSwitch": true, /* Report errors for fallthrough cases in switch statement. */
|
||||
// "noUncheckedIndexedAccess": true, /* Include 'undefined' in index signature results */
|
||||
// "noImplicitOverride": true, /* Ensure overriding members in derived classes are marked with an 'override' modifier. */
|
||||
// "noPropertyAccessFromIndexSignature": true, /* Require undeclared properties from index signatures to use element accesses. */
|
||||
|
||||
/* Module Resolution Options */
|
||||
"moduleResolution": "node", /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */
|
||||
// "baseUrl": "./", /* Base directory to resolve non-absolute module names. */
|
||||
// "paths": {}, /* A series of entries which re-map imports to lookup locations relative to the 'baseUrl'. */
|
||||
"rootDirs": ["./ts", "./hwe/ts"], /* List of root folders whose combined content represents the structure of the project at runtime. */
|
||||
//"typeRoots": ["./typings"], /* List of folders to include type definitions from. */
|
||||
//"types": ["ts/common_path.d.ts"], /* Type declaration files to be included in compilation. */
|
||||
// "allowSyntheticDefaultImports": true, /* Allow default imports from modules with no default export. This does not affect code emit, just typechecking. */
|
||||
"esModuleInterop": true, /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */
|
||||
// "preserveSymlinks": true, /* Do not resolve the real path of symlinks. */
|
||||
// "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */
|
||||
|
||||
/* Source Map Options */
|
||||
// "sourceRoot": "", /* Specify the location where debugger should locate TypeScript files instead of source locations. */
|
||||
// "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */
|
||||
// "inlineSourceMap": true, /* Emit a single file with source maps instead of having a separate file. */
|
||||
// "inlineSources": true, /* Emit the source alongside the sourcemaps within a single file; requires '--inlineSourceMap' or '--sourceMap' to be set. */
|
||||
|
||||
/* Experimental Options */
|
||||
// "experimentalDecorators": true, /* Enables experimental support for ES7 decorators. */
|
||||
// "emitDecoratorMetadata": true, /* Enables experimental support for emitting type metadata for decorators. */
|
||||
|
||||
/* Advanced Options */
|
||||
"skipLibCheck": true, /* Skip type checking of declaration files. */
|
||||
"forceConsistentCasingInFileNames": true /* Disallow inconsistently-cased references to the same file. */
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
const path = require('path');
|
||||
|
||||
module.exports = [
|
||||
{
|
||||
name: 'ingame',
|
||||
resolve: {
|
||||
extensions: [".js", ".ts", ".tsx"]
|
||||
},
|
||||
entry: {
|
||||
inheritPoint: './hwe/ts/inheritPoint.ts',
|
||||
},
|
||||
output: {
|
||||
filename: '[name].js',
|
||||
path: path.resolve(__dirname, 'hwe/js'),
|
||||
},
|
||||
mode: 'production',
|
||||
devtool: 'source-map',
|
||||
module: {
|
||||
rules: [{
|
||||
test: /\.(ts|tsx)$/,
|
||||
exclude: /(node_modules)/,
|
||||
use: {
|
||||
loader: 'babel-loader',
|
||||
options: {
|
||||
presets: [
|
||||
'@babel/preset-env',
|
||||
'@babel/preset-typescript'
|
||||
]
|
||||
}
|
||||
}
|
||||
}]
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'gateway',
|
||||
resolve: {
|
||||
extensions: [".js", ".ts", ".tsx"]
|
||||
},
|
||||
entry: {
|
||||
//test: './ts/test.ts',
|
||||
},
|
||||
output: {
|
||||
filename: '[name].js',
|
||||
path: path.resolve(__dirname, 'js'),
|
||||
},
|
||||
mode: 'none',
|
||||
devtool: 'source-map',
|
||||
module: {
|
||||
rules: [{
|
||||
test: /\.(ts|tsx)$/,
|
||||
exclude: /(node_modules)/,
|
||||
use: {
|
||||
loader: 'babel-loader',
|
||||
options: {
|
||||
presets: [
|
||||
'@babel/preset-env',
|
||||
'@babel/preset-typescript'
|
||||
]
|
||||
}
|
||||
}
|
||||
}]
|
||||
},
|
||||
},
|
||||
]
|
||||
Reference in New Issue
Block a user