Compare commits

..
36 Commits
Author SHA1 Message Date
Hide_D e0d1a0a612 아이템 효과 텍스트 수정 2021-04-30 22:36:24 +09:00
Hide_D 3040996671 무쌍 누락분 수정 2021-04-30 16:35:34 +09:00
Hide_D dd830e7500 TypeCode 추가 2021-04-29 22:38:46 +09:00
Hide_D d2dfe2c418 전투 수비 파트 약 상향 2021-04-29 21:10:47 +09:00
Hide_D 139fb6b6e0 국가 규모 승급시 아이템 습득 방식 변경 2021-04-29 20:31:32 +09:00
Hide_D c4f6976c42 유니크 아이템에 효과 추가 2021-04-29 19:50:12 +09:00
Hide_D ab428fc104 유니크 기본 획득 확률 변경 2021-04-29 18:49:19 +09:00
Hide_D aa97f78acd 무쌍 초반 버프, 후반 너프 2021-04-29 18:47:55 +09:00
Hide_D dbce900aeb 유니크 중복 획득 가능 2021-04-29 18:44:09 +09:00
Hide_D 30b382e2e7 초반 등록 NPC 30명 2021-04-29 18:30:46 +09:00
Hide_D 433c4abb86 fix: 이민족 종료 시점 2021-04-11 23:17:47 +09:00
Hide_D 64404e4092 fix: 이민족 종료조건 추가 2021-04-11 21:22:06 +09:00
Hide_D 08d483af8a fix: 후방 워프 인구 충분 판단 기준 수정 2021-04-10 16:01:21 +09:00
Hide_D fa19c17941 fix: AI 발령 턴 오류 수정 2021-04-10 15:39:03 +09:00
Hide_D c896a999ad fix: 전방 도시가 '관'처럼 인구가 적은 경우 후방 워프하지 않는 버그 수정
feat: 후방 발령 관련 로직도 후방 워프와 유사하게 재 적용
2021-04-10 11:51:10 +09:00
Hide_D f9bca935ac fix: 장수수 카운트에 "의병장"을 포함하여 계산하는 버그 수정 2021-04-02 14:39:57 +09:00
Hide_D 7abf274d89 이민족 난이도 기본 수치 변경 2021-03-29 22:45:43 +09:00
Hide_D e2ad417306 feat: 이민족 등장 2021-03-28 16:31:01 +09:00
Hide_D 2ea9655f6b fix: 이민족 2021-03-28 05:57:53 +09:00
Hide_D f450d5d9de fix: 수비자 도시 버그
fix: RaiseInvader 버그 수정 중
2021-03-28 04:12:10 +09:00
Hide_D f8f4b73a09 feat: RaiserInvader 초기 구현 2021-03-28 03:13:03 +09:00
Hide_D 926d96732d fix: 가상 역사 모드에서 후계자 지정이 사실 모드 설정을 따라가는 버그 수정 2021-03-23 13:24:34 +09:00
Hide_D 167113d6a3 fix: 빙의 해제시 owner 값 버그 수정 2021-03-23 13:19:40 +09:00
Hide_D 911cb614a5 fix: RegNPC 버그 수정, event handler 규격 버그 수정 2021-03-19 18:09:53 +09:00
Hide_D 7a939b7024 fix: RegNPC 버그 수정 2021-03-19 17:44:34 +09:00
Hide_D 6e57a60997 RegNPC 버그 수정 2021-03-19 17:36:13 +09:00
Hide_D 9f1151e699 fix: can부대구출발령 없음 2021-03-19 17:22:48 +09:00
Hide_D 3fbe1fb63d 디버그2 2021-02-28 01:39:47 +09:00
Hide_D d4906eec5a 디버그 코드 추가 2021-02-28 01:33:58 +09:00
Hide_D ebe0663e74 에러 로그용 추가 2021-02-28 01:05:27 +09:00
Hide_D 04c89b9711 긴급 호출 대비 2021-02-21 00:40:49 +09:00
Hide_D 4f2bc874e5 initFull을 할 필요가 없었던 것! 2021-02-10 21:24:04 +09:00
Hide_D 316ac5c3c8 불가침인데도 선포 가능한 버그 수정 2021-01-12 17:14:36 +09:00
Hide_D 7882aa667e 관리자 도구 수정 2021-01-07 22:22:04 +09:00
Hide_D 8b8d5eecbf 모반시도 버그 수정 2021-01-07 01:12:06 +09:00
Hide_D 65b76643ee feat: 빙의일람에 장수 선택 내역
fix: 장수 선택 내역에서 owner_name 미반영 버그 수정
fix: 온라인 장수에서 npc가 뜨는 버그 수정
2021-01-03 18:31:18 +09:00
70 changed files with 1041 additions and 289 deletions
+1 -1
View File
@@ -117,7 +117,7 @@ function logError(string $err, string $errstr, string $errpath, array $trace)
]);
}
function logErrorByCustomHandler(int $errno, string $errstr, string $errfile, int $errline, array $errcontext)
function logErrorByCustomHandler(int $errno, string $errstr, string $errfile, int $errline, array $errcontext=null)
{
if (!(error_reporting() & $errno)) {
// This error code is not included in error_reporting, so let it fall
+6 -1
View File
@@ -59,8 +59,13 @@ foreach (getAllNationStaticInfo() as $nation) {
$nationName[$nation['nation']] = $nation['name'];
}
$generalList = $db->query('SELECT npc,nation,name,owner_name,special,special2,personal,leadership,strength,intel,leadership+strength+intel as sum,explevel,experience,dedication from general where npc=1');
$generalListFromPool = $db->query('SELECT npc,nation,name,owner_name,special,special2,personal,leadership,strength,intel,leadership+strength+intel as sum,explevel,experience,dedication from general JOIN select_pool on general.no = select_pool.general_id where npc=0');
if($generalListFromPool){
$generalList = array_merge($generalListFromPool, $generalList);
}
$sortType = [
1 => ['name', true],
2 => ['nation', true],
+1
View File
@@ -162,6 +162,7 @@ if(!key_exists($citylist, CityConst::all())){
if($userGrade >= 5){
$valid = true;
$showDetailedInfo = true;
}
if(!$valid) {
+47 -15
View File
@@ -1224,7 +1224,7 @@ function updateOnline()
//동접수
$before5Min = TimeUtil::nowAddMinutes(-5);
$onlineUser = $db->query('SELECT no,name,nation FROM general WHERE lastrefresh > %s', $before5Min);
$onlineUser = $db->query('SELECT no,name,nation FROM general WHERE lastrefresh > %s AND npc < 2', $before5Min);
$onlineNum = count($onlineUser);
$onlineNationUsers = Util::arrayGroupBy($onlineUser, 'nation');
@@ -1537,7 +1537,18 @@ function giveRandomUniqueItem(General $general, string $acquireType): bool
//일단은 '획득' 시에만 동작하므로 이대로 사용하기로...
$occupiedUnique = [];
$invalidItemType = [];
foreach(array_keys(GameConst::$allItems) as $itemType){
$ownItem = $general->getItems()[$itemType]??null;
if($ownItem !== null && !$ownItem->isBuyable()){
$invalidItemType[$itemType] = true;
}
}
foreach (array_keys(GameConst::$allItems) as $itemType) {
if(key_exists($itemType, $invalidItemType)){
continue;
}
foreach ($db->queryAllLists('SELECT %b, count(*) as cnt FROM general GROUP BY %b', $itemType, $itemType) as [$itemCode, $cnt]) {
$itemClass = buildItemClass($itemCode);
if (!$itemClass) {
@@ -1551,6 +1562,9 @@ function giveRandomUniqueItem(General $general, string $acquireType): bool
}
foreach (GameConst::$allItems as $itemType => $itemCategories) {
if(key_exists($itemType, $invalidItemType)){
continue;
}
foreach ($itemCategories as $itemCode => $cnt) {
if (!key_exists($itemCode, $occupiedUnique)) {
$availableUnique[] = [[$itemType, $itemCode], $cnt];
@@ -1604,38 +1618,56 @@ function tryUniqueItemLottery(General $general, string $acquireType = '아이템
return false;
}
$itemTypeCnt = count(GameConst::$allItems);
$trialCnt = $itemTypeCnt;
foreach ($general->getItems() as $item) {
if (!$item) {
continue;
}
if (!$item->isBuyable()) {
return false;
$trialCnt -= 1;
}
}
if($trialCnt <= 0){
LogText("{$general->getName()}, {$general->getID()} 모든 아이템", $trialCnt);
return false;
}
$scenario = $gameStor->scenario;
$genCount = $db->queryFirstField('SELECT count(*) FROM general WHERE npc<2');
if ($scenario < 100) {
$prob = 1 / ($genCount * 5); // 5~6개월에 하나씩 등장
$prob = 1 / ($genCount * 3 * $itemTypeCnt); // 3~4개월에 하나씩 등장
} else {
$prob = 1 / $genCount; // 1~2개월에 하나씩 등장
$prob = 1 / ($genCount * $itemTypeCnt); // 1~2개월에 하나씩 등장
}
if ($acquireType == '설문조사') {
$prob = 1 / ($genCount * 0.7 / 3); // 투표율 70%, 설문조사 한번에 2~3개 등장
$prob = 1 / ($genCount * $itemTypeCnt * 0.7 / 3); // 투표율 70%, 설문조사 한번에 2~3개 등장
} else if ($acquireType == '랜덤 임관') {
$prob = 1 / ($genCount / 10 / 2); // 랜임시 2개(10%) 등장(200명중 20명 랜임시도?)
$prob = 1 / ($genCount * $itemTypeCnt / 10 / 2); // 랜임시 2개(10%) 등장(200명중 20명 랜임시도?)
} else if ($acquireType == '건국') {
$prob = 1 / ($genCount / 10 / 4); // 건국시 4개(20%) 등장(200명시 20국 정도 됨)
$prob = 1 / ($genCount * $itemTypeCnt / 10 / 4); // 건국시 4개(20%) 등장(200명시 20국 정도 됨)
}
$prob = Util::valueFit($prob, null, 1 / 3);
$prob = Util::valueFit($prob, null, 1 / 4);//최대치 감소
$result = false;
if (!Util::randBool($prob)) {
foreach(Util::range($trialCnt) as $_idx){
if (Util::randBool($prob)) {
$result = true;
break;
}
}
if(!$result){
LogText("{$general->getName()}, {$general->getID()} 유니크 실패 {$trialCnt}", $prob);
return false;
}
LogText("{$general->getName()}, {$general->getID()} 유니크 성공 {$trialCnt}", $prob);
return giveRandomUniqueItem($general, $acquireType);
}
@@ -1736,7 +1768,7 @@ function nextRuler(General $general)
$db = DB::db();
$gameStor = KVStorage::getStorage($db, 'game_env');
[$year, $month] = $gameStor->getValuesAsArray(['year', 'month']);
[$year, $month, $fiction] = $gameStor->getValuesAsArray(['year', 'month', 'fiction']);
$nation = $general->getStaticNation();
$nationName = $nation['name'];
$nationID = $nation['nation'];
@@ -1744,7 +1776,7 @@ function nextRuler(General $general)
$candidate = null;
//npc or npc유저인 경우 후계 찾기
if ($general->getNPCType() > 0) {
if (!$fiction && $general->getNPCType() > 0) {
$candidate = $db->queryFirstRow(
'SELECT no,name,officer_level,IF(ABS(affinity-%i)>75,150-ABS(affinity-%i),ABS(affinity-%i)) as npcmatch2 from general where nation=%i and officer_level!=12 and 1 <= npc and npc<=3 order by npcmatch2,rand() LIMIT 1',
$general->getVar('affinity'),
+8 -4
View File
@@ -627,14 +627,15 @@ function updateNationState()
$uniqueLotteryWeightList = [];
foreach ($nationGenList as $nationGen) {
$hasUnique = false;
$trialCnt = count(GameConst::$allItems);
foreach ($nationGen->getItems() as $item) {
if (!$item->isBuyable()) {
$hasUnique = true;
break;
$trialCnt -= 1;
}
}
if ($hasUnique) {
if ($trialCnt <= 0) {
continue;
}
@@ -647,6 +648,9 @@ function updateNationState()
} else if ($nationGen->getVar('officer_level') > 4) {
$score += 35;
}
$score *= $trialCnt;
$uniqueLotteryWeightList[$nationGen->getID()] = [$nationGen, $score];
}
+4 -1
View File
@@ -115,7 +115,10 @@ foreach(GameConst::$generalPoolAllowOption as $allowOption){
}
}
$userNick = $ownerInfo['name'];
$builder->setOwner($userID);
$builder->setOwnerName($userNick);
$builder->setKillturn(5);
$builder->setNPCType(0);
$builder->setAuxVar('next_change', TimeUtil::nowAddMinutes(12 * $env['turnterm']));
@@ -135,7 +138,7 @@ $db->update('select_pool',[
'reserved_until'=>null,
], '(owner=%i or reserved_until < %s) AND general_id is NULL', $userID, $now);
$userNick = $ownerInfo['name'];
$josaYi = JosaUtil::pick($userNick, '이');
$generalName = $builder->getGeneralName();
$josaRo = JosaUtil::pick($generalName, '로');
+1
View File
@@ -132,6 +132,7 @@ if(key_exists('specialWar', $info)){
$generalObj->setAuxVar('next_change', TimeUtil::nowAddMinutes(12 * $turnterm));
$userNick = $ownerInfo['name'];
$generalObj->setVar('owner_name', $userNick);
$josaYi = JosaUtil::pick($userNick, '이');
$generalName = $info['generalName'];
+2 -2
View File
@@ -185,10 +185,10 @@ if($relYear < 3){
$experience = 0;
}
else{
$expGenCount = $db->queryFirstField('SELECT count(*) FROM general WHERE nation != 0 AND npc < 5');
$expGenCount = $db->queryFirstField('SELECT count(*) FROM general WHERE nation != 0 AND npc < 4');
$targetGenOrder = Util::round($expGenCount * 0.2);
$experience = $db->queryFirstField(
'SELECT experience FROM general WHERE nation != 0 AND npc < 5 ORDER BY experience ASC LIMIT %i, 1',
'SELECT experience FROM general WHERE nation != 0 AND npc < 4 ORDER BY experience ASC LIMIT %i, 1',
$targetGenOrder - 1
);
$experience *= 0.8;
+2 -1
View File
@@ -43,7 +43,7 @@ function processWar(General $attackerGeneral, array $rawAttackerNation, array $r
$iterDefender = new \ArrayIterator($defenderList);
$iterDefender->rewind();
$getNextDefender = function(?WarUnit $prevDefender, bool $reqNext) use ($iterDefender, $rawDefenderNation, $db) {
$getNextDefender = function(?WarUnit $prevDefender, bool $reqNext) use ($iterDefender, $rawDefenderNation, $rawDefenderCity, $db) {
if($prevDefender !== null){
$prevDefender->applyDB($db);
}
@@ -57,6 +57,7 @@ function processWar(General $attackerGeneral, array $rawAttackerNation, array $r
}
$nextDefender = $iterDefender->current();
$nextDefender->setRawCity($rawDefenderCity);
if(extractBattleOrder($nextDefender) <= 0){
return null;
}
@@ -6,4 +6,17 @@ use \sammo\General;
class che_명마_07_기주마 extends \sammo\BaseStatItem{
protected $cost = 200;
protected $buyable = false;
public function __construct()
{
parent::__construct();
$this->info .= "<br>[전투] 공격 시 페이즈 +1";
}
public function onCalcStat(General $general, string $statName, $value, $aux=null){
if($statName === 'initWarPhase'){
return $value + 1;
}
return $value;
}
}
@@ -1,9 +1,26 @@
<?php
namespace sammo\ActionItem;
use sammo\BaseWarUnitTrigger;
use \sammo\iAction;
use \sammo\General;
use sammo\WarUnit;
use sammo\WarUnitTrigger\che_퇴각부상무효;
use sammo\WarUnitTriggerCaller;
class che_명마_07_백마 extends \sammo\BaseStatItem{
protected $cost = 200;
protected $buyable = false;
public function __construct()
{
parent::__construct();
$this->info .= "<br>[전투] 전투 종료로 인한 부상 없음";
}
public function getBattleInitSkillTriggerList(WarUnit $unit):?WarUnitTriggerCaller{
return new WarUnitTriggerCaller(
new che_퇴각부상무효($unit, BaseWarUnitTrigger::TYPE_ITEM),
);
}
}
@@ -1,9 +1,27 @@
<?php
namespace sammo\ActionItem;
use sammo\BaseWarUnitTrigger;
use \sammo\iAction;
use \sammo\General;
use sammo\WarUnit;
use sammo\WarUnitTrigger\che_퇴각부상무효;
use sammo\WarUnitTriggerCaller;
class che_명마_12_사륜거 extends \sammo\BaseStatItem{
protected $cost = 200;
protected $buyable = false;
public function __construct()
{
parent::__construct();
$this->info .= "<br>[전투] 전투 종료로 인한 부상 없음";
}
public function getBattleInitSkillTriggerList(WarUnit $unit):?WarUnitTriggerCaller{
return new WarUnitTriggerCaller(
new che_퇴각부상무효($unit, BaseWarUnitTrigger::TYPE_ITEM),
);
}
}
@@ -2,9 +2,26 @@
namespace sammo\ActionItem;
use \sammo\iAction;
use \sammo\General;
use sammo\WarUnit;
use sammo\WarUnitTrigger\che_저격발동;
use sammo\WarUnitTrigger\che_저격시도;
use sammo\WarUnitTriggerCaller;
class che_무기_02_단궁 extends \sammo\BaseStatItem{
protected $cost = 3000;
protected $buyable = true;
protected $reqSecu = 2000;
public function __construct()
{
parent::__construct();
$this->info .= "<br>[전투] 새로운 상대와 전투 시 1% 확률로 저격 발동, 성공 시 사기+10";
}
public function getBattlePhaseSkillTriggerList(WarUnit $unit):?WarUnitTriggerCaller{
return new WarUnitTriggerCaller(
new che_저격시도($unit, che_저격시도::TYPE_ITEM + che_저격시도::TYPE_DEDUP_TYPE_BASE * 102, 0.01, 10, 30),
new che_저격발동($unit, che_저격발동::TYPE_ITEM)
);
}
}
@@ -2,8 +2,25 @@
namespace sammo\ActionItem;
use \sammo\iAction;
use \sammo\General;
use sammo\WarUnit;
use sammo\WarUnitTrigger\che_저격발동;
use sammo\WarUnitTrigger\che_저격시도;
use sammo\WarUnitTriggerCaller;
class che_무기_07_맥궁 extends \sammo\BaseStatItem{
protected $cost = 200;
protected $buyable = false;
public function __construct()
{
parent::__construct();
$this->info .= "<br>[전투] 새로운 상대와 전투 시 20% 확률로 저격 발동, 성공 시 사기+10";
}
public function getBattlePhaseSkillTriggerList(WarUnit $unit):?WarUnitTriggerCaller{
return new WarUnitTriggerCaller(
new che_저격시도($unit, che_저격시도::TYPE_ITEM + che_저격시도::TYPE_DEDUP_TYPE_BASE * 107, 0.2, 20, 40),
new che_저격발동($unit, che_저격발동::TYPE_ITEM)
);
}
}
@@ -2,8 +2,25 @@
namespace sammo\ActionItem;
use \sammo\iAction;
use \sammo\General;
use sammo\WarUnit;
use sammo\WarUnitTrigger\che_저격발동;
use sammo\WarUnitTrigger\che_저격시도;
use sammo\WarUnitTriggerCaller;
class che_무기_09_동호비궁 extends \sammo\BaseStatItem{
protected $cost = 200;
protected $buyable = false;
public function __construct()
{
parent::__construct();
$this->info .= "<br>[전투] 새로운 상대와 전투 시 20% 확률로 저격 발동, 성공 시 사기+10";
}
public function getBattlePhaseSkillTriggerList(WarUnit $unit):?WarUnitTriggerCaller{
return new WarUnitTriggerCaller(
new che_저격시도($unit, che_저격시도::TYPE_ITEM + che_저격시도::TYPE_DEDUP_TYPE_BASE * 109, 0.15, 20, 40),
new che_저격발동($unit, che_저격발동::TYPE_ITEM)
);
}
}
@@ -2,8 +2,25 @@
namespace sammo\ActionItem;
use \sammo\iAction;
use \sammo\General;
use sammo\WarUnit;
use sammo\WarUnitTrigger\che_저격발동;
use sammo\WarUnitTrigger\che_저격시도;
use sammo\WarUnitTriggerCaller;
class che_무기_11_이광궁 extends \sammo\BaseStatItem{
protected $cost = 200;
protected $buyable = false;
public function __construct()
{
parent::__construct();
$this->info .= "<br>[전투] 새로운 상대와 전투 시 10% 확률로 저격 발동, 성공 시 사기+10";
}
public function getBattlePhaseSkillTriggerList(WarUnit $unit):?WarUnitTriggerCaller{
return new WarUnitTriggerCaller(
new che_저격시도($unit, che_저격시도::TYPE_ITEM + che_저격시도::TYPE_DEDUP_TYPE_BASE * 111, 0.10, 20, 40),
new che_저격발동($unit, che_저격발동::TYPE_ITEM)
);
}
}
@@ -2,8 +2,25 @@
namespace sammo\ActionItem;
use \sammo\iAction;
use \sammo\General;
use sammo\WarUnit;
use sammo\WarUnitTrigger\che_저격발동;
use sammo\WarUnitTrigger\che_저격시도;
use sammo\WarUnitTriggerCaller;
class che_무기_13_양유기궁 extends \sammo\BaseStatItem{
protected $cost = 200;
protected $buyable = false;
public function __construct()
{
parent::__construct();
$this->info .= "<br>[전투] 새로운 상대와 전투 시 10% 확률로 저격 발동, 성공 시 사기+10";
}
public function getBattlePhaseSkillTriggerList(WarUnit $unit):?WarUnitTriggerCaller{
return new WarUnitTriggerCaller(
new che_저격시도($unit, che_저격시도::TYPE_ITEM + che_저격시도::TYPE_DEDUP_TYPE_BASE * 113, 0.05, 20, 40),
new che_저격발동($unit, che_저격발동::TYPE_ITEM)
);
}
}
@@ -21,8 +21,8 @@ class che_반계_백우선 extends \sammo\BaseItem{
public function getBattlePhaseSkillTriggerList(WarUnit $unit):?WarUnitTriggerCaller{
return new WarUnitTriggerCaller(
new WarActivateSkills($unit, BaseWarUnitTrigger::TYPE_NONE, false, '계략약화'),
new che_반계시도($unit),
new WarActivateSkills($unit, BaseWarUnitTrigger::TYPE_ITEM +BaseWarUnitTrigger::TYPE_DEDUP_TYPE_BASE*301, false, '계략약화'),
new che_반계시도($unit, BaseWarUnitTrigger::TYPE_ITEM +BaseWarUnitTrigger::TYPE_DEDUP_TYPE_BASE*301),
new che_반계발동($unit)
);
}
@@ -21,8 +21,8 @@ class che_반계_파초선 extends \sammo\BaseItem{
public function getBattlePhaseSkillTriggerList(WarUnit $unit):?WarUnitTriggerCaller{
return new WarUnitTriggerCaller(
new WarActivateSkills($unit, BaseWarUnitTrigger::TYPE_NONE, false, '계략약화'),
new che_반계시도($unit),
new WarActivateSkills($unit, BaseWarUnitTrigger::TYPE_ITEM +BaseWarUnitTrigger::TYPE_DEDUP_TYPE_BASE*302, false, '계략약화'),
new che_반계시도($unit, BaseWarUnitTrigger::TYPE_ITEM +BaseWarUnitTrigger::TYPE_DEDUP_TYPE_BASE*302),
new che_반계발동($unit)
);
}
@@ -7,4 +7,17 @@ class che_서적_01_효경전 extends \sammo\BaseStatItem{
protected $cost = 1000;
protected $buyable = true;
protected $reqSecu = 1000;
public function __construct()
{
parent::__construct();
$this->info .= "<br>[전투] 계략 시도 확률 +1%p";
}
public function onCalcStat(General $general, string $statName, $value, $aux=null){
if($statName === 'warMagicTrialProb'){
return $value + 0.01;
}
return $value;
}
}
@@ -7,4 +7,17 @@ class che_서적_02_회남자 extends \sammo\BaseStatItem{
protected $cost = 3000;
protected $buyable = true;
protected $reqSecu = 2000;
public function __construct()
{
parent::__construct();
$this->info .= "<br>[전투] 계략 시도 확률 +1%p";
}
public function onCalcStat(General $general, string $statName, $value, $aux=null){
if($statName === 'warMagicTrialProb'){
return $value + 0.01;
}
return $value;
}
}
@@ -7,4 +7,17 @@ class che_서적_03_변도론 extends \sammo\BaseStatItem{
protected $cost = 6000;
protected $buyable = true;
protected $reqSecu = 3000;
public function __construct()
{
parent::__construct();
$this->info .= "<br>[전투] 계략 시도 확률 +2%p";
}
public function onCalcStat(General $general, string $statName, $value, $aux=null){
if($statName === 'warMagicTrialProb'){
return $value + 0.02;
}
return $value;
}
}
@@ -7,4 +7,17 @@ class che_서적_04_건상역주 extends \sammo\BaseStatItem{
protected $cost = 10000;
protected $buyable = true;
protected $reqSecu = 4000;
public function __construct()
{
parent::__construct();
$this->info .= "<br>[전투] 계략 시도 확률 +2%p";
}
public function onCalcStat(General $general, string $statName, $value, $aux=null){
if($statName === 'warMagicTrialProb'){
return $value + 0.02;
}
return $value;
}
}
@@ -7,4 +7,17 @@ class che_서적_05_여씨춘추 extends \sammo\BaseStatItem{
protected $cost = 15000;
protected $buyable = true;
protected $reqSecu = 5000;
public function __construct()
{
parent::__construct();
$this->info .= "<br>[전투] 계략 시도 확률 +3%p";
}
public function onCalcStat(General $general, string $statName, $value, $aux=null){
if($statName === 'warMagicTrialProb'){
return $value + 0.03;
}
return $value;
}
}
@@ -7,4 +7,17 @@ class che_서적_06_사민월령 extends \sammo\BaseStatItem{
protected $cost = 21000;
protected $buyable = true;
protected $reqSecu = 6000;
public function __construct()
{
parent::__construct();
$this->info .= "<br>[전투] 계략 시도 확률 +3%p";
}
public function onCalcStat(General $general, string $statName, $value, $aux=null){
if($statName === 'warMagicTrialProb'){
return $value + 0.03;
}
return $value;
}
}
@@ -1,9 +1,26 @@
<?php
namespace sammo\ActionItem;
use sammo\BaseWarUnitTrigger;
use \sammo\iAction;
use \sammo\General;
use sammo\WarUnit;
use sammo\WarUnitTrigger\WarActivateSkills;
use sammo\WarUnitTriggerCaller;
class che_서적_07_논어 extends \sammo\BaseStatItem{
protected $cost = 200;
protected $buyable = false;
public function __construct()
{
parent::__construct();
$this->info .= "<br>[전투] 상대의 계략 성공 확률 -10%p";
}
public function getBattlePhaseSkillTriggerList(WarUnit $unit):?WarUnitTriggerCaller{
return new WarUnitTriggerCaller(
new WarActivateSkills($unit, BaseWarUnitTrigger::TYPE_ITEM+BaseWarUnitTrigger::TYPE_DEDUP_TYPE_BASE*207, false, '계략약화')
);
}
}
@@ -1,9 +1,28 @@
<?php
namespace sammo\ActionItem;
use sammo\BaseWarUnitTrigger;
use \sammo\iAction;
use \sammo\General;
use sammo\WarUnit;
use sammo\WarUnitTrigger\che_반계발동;
use sammo\WarUnitTrigger\che_반계시도;
use sammo\WarUnitTriggerCaller;
class che_서적_07_사마법 extends \sammo\BaseStatItem{
protected $cost = 200;
protected $buyable = false;
public function __construct()
{
parent::__construct();
$this->info .= "<br>[전투] 상대의 계략을 20% 확률로 되돌림";
}
public function getBattlePhaseSkillTriggerList(WarUnit $unit):?WarUnitTriggerCaller{
return new WarUnitTriggerCaller(
new che_반계시도($unit, BaseWarUnitTrigger::TYPE_ITEM+BaseWarUnitTrigger::TYPE_DEDUP_TYPE_BASE*207, 0.2),
new che_반계발동($unit)
);
}
}
@@ -6,4 +6,17 @@ use \sammo\General;
class che_서적_07_위료자 extends \sammo\BaseStatItem{
protected $cost = 200;
protected $buyable = false;
public function __construct()
{
parent::__construct();
$this->info .= "<br>[전투] 계략 시도 확률 +20%p";
}
public function onCalcStat(General $general, string $statName, $value, $aux=null){
if($statName === 'warMagicTrialProb'){
return $value + 0.2;
}
return $value;
}
}
@@ -6,4 +6,17 @@ use \sammo\General;
class che_서적_08_전론 extends \sammo\BaseStatItem{
protected $cost = 200;
protected $buyable = false;
public function __construct()
{
parent::__construct();
$this->info .= "<br>[전투] 계략 성공 시 대미지 +20%";
}
public function onCalcStat(General $general, string $statName, $value, $aux=null){
if($statName === 'warMagicSuccessDamage'){
return $value * 1.2;
}
return $value;
}
}
@@ -1,9 +1,26 @@
<?php
namespace sammo\ActionItem;
use sammo\BaseWarUnitTrigger;
use \sammo\iAction;
use \sammo\General;
use sammo\WarUnit;
use sammo\WarUnitTrigger\WarActivateSkills;
use sammo\WarUnitTriggerCaller;
class che_서적_11_춘추전 extends \sammo\BaseStatItem{
protected $cost = 200;
protected $buyable = false;
public function __construct()
{
parent::__construct();
$this->info .= "<br>[전투] 상대의 계략 성공 확률 -10%p";
}
public function getBattlePhaseSkillTriggerList(WarUnit $unit):?WarUnitTriggerCaller{
return new WarUnitTriggerCaller(
new WarActivateSkills($unit, BaseWarUnitTrigger::TYPE_ITEM+BaseWarUnitTrigger::TYPE_DEDUP_TYPE_BASE*211, false, '계략약화')
);
}
}
@@ -1,9 +1,28 @@
<?php
namespace sammo\ActionItem;
use sammo\BaseWarUnitTrigger;
use \sammo\iAction;
use \sammo\General;
use sammo\WarUnit;
use sammo\WarUnitTrigger\che_반계발동;
use sammo\WarUnitTrigger\che_반계시도;
use sammo\WarUnitTriggerCaller;
class che_서적_12_산해경 extends \sammo\BaseStatItem{
protected $cost = 200;
protected $buyable = false;
public function __construct()
{
parent::__construct();
$this->info .= "<br>[전투] 상대의 계략을 20% 확률로 되돌림";
}
public function getBattlePhaseSkillTriggerList(WarUnit $unit):?WarUnitTriggerCaller{
return new WarUnitTriggerCaller(
new che_반계시도($unit, BaseWarUnitTrigger::TYPE_ITEM, 0.2),
new che_반계발동($unit)
);
}
}
@@ -27,7 +27,7 @@ class che_의술_상한잡병론 extends \sammo\BaseItem{
public function getBattlePhaseSkillTriggerList(\sammo\WarUnit $unit): ?WarUnitTriggerCaller
{
return new WarUnitTriggerCaller(
new che_전투치료시도($unit, BaseWarUnitTrigger::TYPE_ITEM),
new che_전투치료시도($unit, BaseWarUnitTrigger::TYPE_ITEM+BaseWarUnitTrigger::TYPE_DEDUP_TYPE_BASE*301),
new che_전투치료발동($unit, BaseWarUnitTrigger::TYPE_ITEM)
);
@@ -27,7 +27,7 @@ class che_의술_청낭서 extends \sammo\BaseItem{
public function getBattlePhaseSkillTriggerList(\sammo\WarUnit $unit): ?WarUnitTriggerCaller
{
return new WarUnitTriggerCaller(
new che_전투치료시도($unit, BaseWarUnitTrigger::TYPE_ITEM),
new che_전투치료시도($unit, BaseWarUnitTrigger::TYPE_ITEM+BaseWarUnitTrigger::TYPE_DEDUP_TYPE_BASE*302),
new che_전투치료발동($unit, BaseWarUnitTrigger::TYPE_ITEM)
);
@@ -27,7 +27,7 @@ class che_의술_태평청령 extends \sammo\BaseItem{
public function getBattlePhaseSkillTriggerList(\sammo\WarUnit $unit): ?WarUnitTriggerCaller
{
return new WarUnitTriggerCaller(
new che_전투치료시도($unit, BaseWarUnitTrigger::TYPE_ITEM),
new che_전투치료시도($unit, BaseWarUnitTrigger::TYPE_ITEM+BaseWarUnitTrigger::TYPE_DEDUP_TYPE_BASE*303),
new che_전투치료발동($unit, BaseWarUnitTrigger::TYPE_ITEM)
);
@@ -1,5 +1,7 @@
<?php
namespace sammo\ActionItem;
use sammo\BaseWarUnitTrigger;
use \sammo\iAction;
use \sammo\General;
use \sammo\SpecialityHelper;
@@ -19,7 +21,7 @@ class che_저격_매화수전 extends \sammo\BaseItem{
public function getBattlePhaseSkillTriggerList(WarUnit $unit):?WarUnitTriggerCaller{
return new WarUnitTriggerCaller(
new che_저격시도($unit, che_저격시도::TYPE_ITEM, 0.5, 20, 40),
new che_저격시도($unit, che_저격시도::TYPE_ITEM+BaseWarUnitTrigger::TYPE_DEDUP_TYPE_BASE*304, 0.5, 20, 40),
new che_저격발동($unit, che_저격발동::TYPE_ITEM)
);
}
+3 -1
View File
@@ -1,5 +1,7 @@
<?php
namespace sammo\ActionItem;
use sammo\BaseWarUnitTrigger;
use \sammo\iAction;
use \sammo\General;
use \sammo\SpecialityHelper;
@@ -19,7 +21,7 @@ class che_저격_비도 extends \sammo\BaseItem{
public function getBattlePhaseSkillTriggerList(WarUnit $unit):?WarUnitTriggerCaller{
return new WarUnitTriggerCaller(
new che_저격시도($unit, che_저격시도::TYPE_ITEM, 0.5, 20, 40),
new che_저격시도($unit, che_저격시도::TYPE_ITEM+BaseWarUnitTrigger::TYPE_DEDUP_TYPE_BASE*305, 0.5, 20, 40),
new che_저격발동($unit, che_저격발동::TYPE_ITEM)
);
}
@@ -11,7 +11,7 @@ class event_전투특기_무쌍 extends \sammo\BaseItem{
protected $id = 61;
protected $rawName = '비급';
protected $name = '비급(무쌍)';
protected $info = '[전투] 대미지 +10%, 공격 시 필살 확률 +10%p, <br>승리 수만큼 대미지 0.20%씩 추가 상승(최대40%)<br>승리 수만큼 피해 0.05%씩 감소(최대50%)';
protected $info = '[전투] 대미지 +10%, 피해 -5%, 공격 시 필살 확률 +10%p, <br>승리 수만큼 대미지 0.20%씩 추가 상승(최대40%)<br>승리 수만큼 피해 0.05%씩 감소(최대30%)';
protected $cost = 100;
protected $buyable = true;
protected $consumable = false;
@@ -26,10 +26,10 @@ class event_전투특기_무쌍 extends \sammo\BaseItem{
public function getWarPowerMultiplier(WarUnit $unit):array{
$attackMultiplier = 1.1;
$defenceMultiplier = 1;
$defenceMultiplier = 0.95;
$killnum = $unit->getGeneral()->getRankVar('killnum');
$attackMultiplier += Util::valueFit($killnum * 0.01 * 0.2, null, 0.4);
$defenceMultiplier -= Util::valueFit($killnum * 0.01 * 0.05, null, 0.5);
$defenceMultiplier -= Util::valueFit($killnum * 0.01 * 0.05, null, 0.3);
return [$attackMultiplier, $defenceMultiplier];
}
}
@@ -10,7 +10,7 @@ class che_event_무쌍 extends \sammo\BaseSpecial{
protected $id = 61;
protected $name = '무쌍';
protected $info = '[전투] 대미지 +10%, 공격 시 필살 확률 +10%p, <br>승리 수만큼 대미지 0.20%씩 추가 상승(최대40%)<br>승리 수만큼 피해 0.05%씩 감소(최대50%)';
protected $info = '[전투] 대미지 +10%, 피해 -5%, 공격 시 필살 확률 +10%p, <br>승리 수만큼 대미지 0.20%씩 추가 상승(최대40%)<br>승리 수만큼 피해 0.05%씩 감소(최대30%)';
static $selectWeightType = SpecialityHelper::WEIGHT_NORM;
static $selectWeight = 1;
@@ -30,7 +30,7 @@ class che_event_무쌍 extends \sammo\BaseSpecial{
$defenceMultiplier = 1;
$killnum = $unit->getGeneral()->getRankVar('killnum');
$attackMultiplier += Util::valueFit($killnum * 0.01 * 0.2, null, 0.4);
$defenceMultiplier -= Util::valueFit($killnum * 0.01 * 0.05, null, 0.5);
$defenceMultiplier -= Util::valueFit($killnum * 0.01 * 0.05, null, 0.3);
return [$attackMultiplier, $defenceMultiplier];
}
}
+3 -3
View File
@@ -10,7 +10,7 @@ class che_무쌍 extends \sammo\BaseSpecial{
protected $id = 61;
protected $name = '무쌍';
protected $info = '[전투] 대미지 +10%, 공격 시 필살 확률 +10%p, <br>승리 수만큼 대미지 0.20%씩 추가 상승(최대40%)<br>승리 수만큼 피해 0.05%씩 감소(최대50%)';
protected $info = '[전투] 대미지 +10%, 피해 -5%, 공격 시 필살 확률 +10%p, <br>승리 수만큼 대미지 0.20%씩 추가 상승(최대40%)<br>승리 수만큼 피해 0.05%씩 감소(최대30%)';
static $selectWeightType = SpecialityHelper::WEIGHT_NORM;
static $selectWeight = 1;
@@ -27,10 +27,10 @@ class che_무쌍 extends \sammo\BaseSpecial{
public function getWarPowerMultiplier(WarUnit $unit):array{
$attackMultiplier = 1.1;
$defenceMultiplier = 1;
$defenceMultiplier = 0.95;
$killnum = $unit->getGeneral()->getRankVar('killnum');
$attackMultiplier += Util::valueFit($killnum * 0.01 * 0.2, null, 0.4);
$defenceMultiplier -= Util::valueFit($killnum * 0.01 * 0.05, null, 0.5);
$defenceMultiplier -= Util::valueFit($killnum * 0.01 * 0.05, null, 0.3);
return [$attackMultiplier, $defenceMultiplier];
}
}
+2
View File
@@ -120,6 +120,7 @@ class AutorunGeneralPolicy{
$priority = [];
foreach($serverPolicy['priority'] as $priorityItem){
if(!property_exists($this, $priorityItem)){
trigger_error ("{$priorityItem}이 없음", E_USER_NOTICE );
continue;
}
$priority[] = $priorityItem;
@@ -133,6 +134,7 @@ class AutorunGeneralPolicy{
$priority = [];
foreach($nationPolicy['priority'] as $priorityItem){
if(!property_exists($this, $priorityItem)){
trigger_error ("{$priorityItem}이 없음", E_USER_NOTICE );
continue;
}
$priority[] = $priorityItem;
+3
View File
@@ -85,6 +85,7 @@ class AutorunNationPolicy {
public $can부대전방발령 = true;
public $can부대후방발령 = true;
public $can부대구출발령 = true;
public $can부대유저장후방발령 = true;
public $can유저장후방발령 = true;
@@ -180,6 +181,7 @@ class AutorunNationPolicy {
if($serverPolicy){
foreach($serverPolicy['values']??[] as $policy=>$value){
if(!property_exists($this, $policy)){
trigger_error ("{$policy}이 없음", E_USER_NOTICE );
continue;
}
$this->{$policy} = $value;
@@ -194,6 +196,7 @@ class AutorunNationPolicy {
if($nationPolicy){
foreach($nationPolicy['values']??[] as $policy=>$value){
if(!property_exists($this, $policy)){
trigger_error ("{$policy}이 없음", E_USER_NOTICE );
continue;
}
$this->{$policy} = $value;
+1
View File
@@ -7,6 +7,7 @@ abstract class BaseWarUnitTrigger extends ObjectTrigger{
const TYPE_NONE = 0;
const TYPE_ITEM = 1;
const TYPE_CONSUMABLE_ITEM = 1 | 2;
const TYPE_DEDUP_TYPE_BASE = 1024;
protected $raiseType = self::TYPE_NONE;
@@ -178,14 +178,14 @@ class che_랜덤임관 extends Command\GeneralCommand{
$generalsCnt = [];
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 < 5 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 < 4 AND nation.gennum < %i AND nation.scout=0 AND nation.nation NOT IN %li GROUP BY general.nation, general.npc',
$genLimit,
$notIn
);
}
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 < 5 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 < 4 AND nation.gennum < %i AND nation.scout=0 GROUP BY general.nation, general.npc',
$genLimit
);
}
@@ -81,7 +81,7 @@ class che_모반시도 extends Command\GeneralCommand{
$nationName = $this->nation['name'];
$logger = $general->getLogger();
$lordLogger = $this->destGeneralObj->getLogger();
$lordLogger = $lordGeneral->getLogger();
$general->setVar('officer_level', 12);
$general->setVar('officer_city', 0);
@@ -178,7 +178,7 @@ class che_인재탐색 extends Command\GeneralCommand
$avgGen = $db->queryFirstRow(
'SELECT avg(dedication) as ded,avg(experience) as exp,
avg(dex1+dex2+dex3+dex4) as dex_t, avg(age) as age, avg(dex5) as dex5
from general where npc < 5'
from general where npc < 4'
);
$pickTypeList = ['무' => 6, '지' => 6, '무지' => 3];
@@ -95,6 +95,7 @@ class che_선전포고 extends Command\NationCommand
ConstraintHelper::DisallowDiplomacyBetweenStatus([
0 => '아국과 이미 교전중입니다.',
1 => '아국과 이미 선포중입니다.',
7 => '불가침국입니다.'
]),
];
}
+1 -1
View File
@@ -3,7 +3,7 @@ namespace sammo\Event;
abstract class Action{
//public abstract function __construct(...$args);
public abstract function run($env=null);
public abstract function run(array $env);
public static function build($actionArgs):Action{
if(!is_array($actionArgs)){
@@ -0,0 +1,46 @@
<?php
namespace sammo\Event\Action;
use function sammo\getNationStaticInfo;
use sammo\DB;
use sammo\Util;
class AutoDeleteInvader extends \sammo\Event\Action{
private $nationID;
public function __construct(int $nationID){
$this->nationID = $nationID;
}
public function run(array $env){
$db = DB::db();
if(getNationStaticInfo($this->nationID)===null){
$db->update('general', [
'killturn'=>5
], 'nation = 0 AND npc = 9');
$eventID = Util::array_get($env['currentEventID']);
$db->delete('event', 'id = %i', $eventID);
return [__CLASS__, "Not Exists"];
}
$db = DB::db();
$onWar = $db->queryFirstField('SELECT count(*) FROM diplomacy WHERE me = %i AND state IN %li', $this->nationID, [0, 1]);
if($onWar){
return [__CLASS__, "On War"];
}
$rulerID = $db->queryFirstField('SELECT no FROM general WHERE nation = %i AND officer_level = 12', $this->nationID);
$db->update('general_turn', [
'action'=>'che_방랑',
'arg'=>'[]',
'brief'=>"이민족 방랑"
], 'general_id = %i', $rulerID);
$db->update('general', [
'killturn'=>5
], 'nation = %i', $this->nationID);
$eventID = Util::array_get($env['currentEventID']);
$db->delete('event', 'id = %i', $eventID);
return [__CLASS__, 'Deleted'];
}
}
+1 -1
View File
@@ -161,7 +161,7 @@ class ChangeCity extends \sammo\Event\Action{
throw new \InvalidArgumentException('올바르지 않은 cond 입니다.');
}
public function run($env=null){
public function run(array $env){
$cities = $this->getTargetCities($env);
DB::db()->update('city',
+1 -1
View File
@@ -7,7 +7,7 @@ class CreateAdminNPC extends \sammo\Event\Action{
}
public function run($env=null){
public function run(array $env){
return [__CLASS__, 'NYI'];
}
+1 -1
View File
@@ -43,7 +43,7 @@ class CreateManyNPC extends \sammo\Event\Action{
}
public function run($env=null){
public function run(array $env){
if($this->npcCount <= 0){
return [__CLASS__, []];
}
+1 -1
View File
@@ -7,7 +7,7 @@ class DeleteEvent extends \sammo\Event\Action{
public function __construct(){
}
public function run($env=null){
public function run(array $env){
$eventID = \sammo\Util::array_get($env['currentEventID']);
if(!$eventID){
+61
View File
@@ -0,0 +1,61 @@
<?php
namespace sammo\Event\Action;
use function sammo\getNationStaticInfo;
use sammo\ActionLogger;
use sammo\CityConst;
use sammo\DB;
use sammo\KVStorage;
use sammo\Util;
class InvaderEnding extends \sammo\Event\Action{
public function __construct(){
}
public function run(array $env){
//FIXME: 조건 체크를 여기서 하지 말라.
$db = DB::db();
$gameStor = KVStorage::getStorage($db, 'game_env');
$logger = new ActionLogger(0, 0, $env['year'], $env['month']);
$isunited = $gameStor->isunited;
if(in_array($isunited, [0, 2])){
return [__CLASS__, "No Invader"];
}
$nationCnt = $db->queryFirstField('SELECT count(*) FROM nation');
if($nationCnt >= 2){
return [__CLASS__, "On Event"];
}
$gameStor = KVStorage::getStorage($db, 'game_env');
$logger = new ActionLogger(0, 0, $env['year'], $env['month']);
$cityCnt = $db->queryFirstField('SELECT count(*) FROM city WHERE nation = 0');
if($cityCnt == 0){
//천통 엔딩
$logger->pushGlobalHistoryLog("<L><b>【이벤트】</b></>이민족을 모두 소탕했습니다!");
$logger->pushGlobalHistoryLog("<L><b>【이벤트】</b></>중원은 당분간 태평성대를 누릴 것입니다.");
}
else if($cityCnt == count(CityConst::all())){
//이민족 엔딩
$logger->pushGlobalHistoryLog("<L><b>【이벤트】</b></>중원은 이민족에 의해 혼란에 빠졌습니다.");
$logger->pushGlobalHistoryLog("<L><b>【이벤트】</b></>백성은 언젠가 영웅이 나타나길 기다립니다.");
}
else{
return [__CLASS__, "On Event"];
}
$gameStor->setValue('isunited', 3);
$logger->flush();
$gameStor->conlimit = $gameStor->conlimit * 100;
$eventID = Util::array_get($env['currentEventID']);
$db->delete('event', 'id = %i', $eventID);
return [__CLASS__, 'Deleted'];
}
}
+198 -57
View File
@@ -1,116 +1,257 @@
<?php
namespace sammo\Event\Action;
use sammo\ActionLogger;
use sammo\CityConst;
use sammo\DB;
use sammo\Json;
use sammo\KVStorage;
use sammo\Scenario\GeneralBuilder;
use sammo\Scenario\Nation;
use sammo\UniqueConst;
use sammo\Util;
use function sammo\getNationStaticInfo;
use function sammo\refreshNationStaticInfo;
/**
* 이민족 침입을 모사
*
* 양수 : 정해진 값. [절대값]
* 음수 : 합산(장수 등), 혹은 평균(기술 등)을 나누어 적용한 값 [상대값]
* 음수 : 합산(장수 등), 혹은 평균(기술 등)을 곱해 적용한 값 [상대값]
*
* event_1.php, 센 이민족 : npcEachCount = -0.5, specAvg = 195, specDist = 5, tech = 15000, dex = 450000
* event_2.php, 약한 이민족 : npcEachCount = -0.5, specAvg = 150, specDist = 20, tech = -1, dex = 0
* event_3.php, 엄청 약한 이민족 : npcEachCount = 100, specAvg = 50, specDist = 5, tech = 0, dex = 0
* event_1.php, 센 이민족 : npcEachCount = -0.5, specAvg = 195, tech = 15000, dex = 450000
* event_2.php, 약한 이민족 : npcEachCount = -0.5, specAvg = 150, tech = -1, dex = 0
* event_3.php, 엄청 약한 이민족 : npcEachCount = 100, specAvg = 50, tech = 0, dex = 0
*/
class RaiseInvader extends \sammo\Event\Action{
class RaiseInvader extends \sammo\Event\Action
{
private $npcEachCount;
private $specAvg;
private $specDist;
private $tech;
private $dex;
const INVADER_LIST = [
'강'=>63,
'저'=>64,
'흉노'=>65,
'남만'=>66,
'산월'=>67,
'오환'=>68,
'왜'=>69
];
public function __construct(
$npcEachCount = -0.5,
int $specAvg = 150,
int $specDist = 20,
int $tech = -1,
int $dex = 0
){
$npcEachCount = -3,
$specAvg = -1.2,
$tech = -1.2,
$dex = -1
) {
$this->npcEachCount = $npcEachCount;
$this->specAvg = $specAvg;
$this->specDist = $specDist;
$this->tech = $tech;
$this->dex = $dex;
if($specDist < 0){
throw new \InvalidArgumentException('specDist는 음수를 지원하지 않습니다.');
}
}
private function moveCapital(){
$cities = array_map(function ($value) {
return $value;
}, static::INVADER_LIST);
private function moveCapital()
{
$cities = [];
foreach (CityConst::all() as $cityObj) {
if ($cityObj->level != 4) {
continue;
}
$cities[] = $cityObj->id;
}
if (count($cities) == 0) {
return [__CLASS__, 0];
}
$db = DB::db();
foreach($db->queryFirstColumn('SELECT capital, nation from nation WHERE capital in %li', $cities) as $row){
foreach ($db->queryFirstColumn('SELECT capital, nation from nation WHERE capital in %li', $cities) as $row) {
list($oldCapital, $nation) = $row;
$newCapital = $db->queryFirstRow('SELECT city from city where nation=%i and city !=%i \
order by rand() limit 1', $nation, $oldCapital);
$db->update('nation', ['capital'=>$newCapital], 'nation=%i', $nation);
$db->update('nation', ['capital' => $newCapital], 'nation=%i', $nation);
$db->update('general', ['city'=>$newCapital], 'nation=%i and city=%i', $nation, $oldCapital);
$db->update('general', ['city' => $newCapital], 'nation=%i and city=%i', $nation, $oldCapital);
}
$db->update('general', [
'officer_level'=>1,
'officer_city'=>0
'officer_level' => 1,
'officer_city' => 0
], 'officer_city in %li', $cities);
$db->update('city', [
'nation'=>0
'nation' => 0,
'front' => 0,
'supply' => 1,
], 'city in %li', $cities);
}
public function run($env=null){
public function run(array $env)
{
$db = DB::db();
$npcEachCount = $this->npcEachCount;
if($npcEachCount < 0){
$npcEachCount =
$db->queryFirstField('SELECT count(no) from general where npc < 9') / count(self::INVADER_LIST);
$npcEachCount /= -1 * $this->npcEachCount;
/** @var \sammo\CityInitDetail[] */
$cities = [];
foreach (CityConst::all() as $cityObj) {
if ($cityObj->level != 4) {
continue;
}
$cities[] = $cityObj;
}
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));
$specAvg = $this->specAvg;
if($specAvg < 0){
$specAvg = $db->queryFirstField('SELECT avg(sum(`leadership` + `strength` + `intel`)) from general where npc < 9');
$specAvg /= -1 * $this->specAvg;
if ($specAvg < 0) {
$specAvg = $db->queryFirstField('SELECT avg((`leadership` + `strength` + `intel`)/3) from general where npc < 4');
$specAvg *= -1 * $this->specAvg;
}
$specAvg = Util::toInt($specAvg);
$tech = $this->tech;
if($tech < 0){
if ($tech < 0) {
$tech = $db->queryFirstField("SELECT avg(tech) from nation where `level`>0");
$tech /= -1 * $this->tech;
$tech *= -1 * $this->tech;
}
$dex = $this->dex;
if($dex < 0){
$dex = $db->queryFirstField("SELECT avg(dex1 + dex2 + dex3 + dex4 + dex5)/5 from nation where `level`>0");
$dex /= -1 * $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);
$this->moveCapital();
//TODO:국가를 만들고
//TODO:장수를 세팅하고
//TODO:외교를 설정한다.
$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),
);
//TODO: 시나리오 구현 후 마무리.
//TODO: 임관 모드가 '랜임모드'인 경우 오랑캐와 충돌하므로 해제해야함.
return [__CLASS__, 'NYI'];
$db->update('general', [
'gold' => 999999,
'rice' => 999999,
], true);
$year = $env['year'];
$invaderNationIDList = [];
refreshNationStaticInfo();
foreach ($cities as $cityObj) {
if ($cityObj->level != 4) {
continue;
}
$lastNationID += 1;
$invaderNationID = $lastNationID;
$invaderNationIDList[] = $invaderNationID;
$invaderName = $cityObj->name;
$nationName = "{$invaderName}";
$nationObj = new Nation($invaderNationID, $nationName, '#800080', 9999999, 9999999, "중원의 부패를 물리쳐라! 이민족 침범!", $tech, "che_병가", 2, [$cityObj->name]);
$nationObj->build($env);
$ruler = (new GeneralBuilder("{$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)
->setGoldRice(99999, 99999);
$ruler->build($env);
$nationObj->addGeneral($ruler);
foreach (Util::range(1, $npcEachCount) as $invaderGenIdx) {
$gen = (new GeneralBuilder("{$invaderName}장수{$invaderGenIdx}", false, null, $invaderNationID))
->setEgo('che_패권')
->setSpecial('che_인덕', 'che_척사')
->setLifeSpan($year - 20, $year + 20)
->setCityID($cityObj->id)
->setNPCType(9)
->setAffinity(999)
->setGoldRice(99999, 99999);
$leadership = Util::randRangeInt(Util::toInt($specAvg * 1.2), Util::toInt($specAvg * 1.4));
$mainStat = Util::randRangeInt(Util::toInt($specAvg * 1.2), Util::toInt($specAvg * 1.4));
$subStat = $specAvg * 3 - $leadership - $mainStat;
if (Util::randBool()) {
//무장
$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', [
'condition' => Json::encode(true),
'action' => Json::encode([["AutoDeleteInvader", $invaderNationID]]),
]);
}
$db->insert('event', [
'condition' => Json::encode(true),
'action' => Json::encode([["InvaderEnding"]]),
]);
$db->update('nation', [
'scout' => 1
], 'nation IN %li', $invaderNationIDList);
$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);
$gameStor = KVStorage::getStorage($db, 'game_env');
$gameStor->setValue('isunited', 1);
refreshNationStaticInfo();
$logger = new ActionLogger(0, 0, $year, $env['month']);
$logger->pushGlobalHistoryLog("<L><b>【이벤트】</b></>각지의 이민족들이 <M>궐기</>합니다!");
$logger->pushGlobalHistoryLog("<L><b>【이벤트】</b></>중원의 전 국가에 <M>선전포고</> 합니다!");
$logger->pushGlobalHistoryLog("<L><b>【이벤트】</b></>이민족의 기세는 그 누구도 막을 수 없을듯 합니다!");
$logger->flush();
$db->update('plock', [
'plock' => 0
], true);
return [__CLASS__, count($invaderNationIDList)];
}
}
}
+7 -5
View File
@@ -3,6 +3,7 @@ namespace sammo\Event\Action;
//이전 RegNPC 함수를 EventAction으로 재구성
class RegNPC extends \sammo\Event\Action{
/** @var \sammo\Scenario\GeneralBuilder */
private $npc;
public function __construct(
@@ -14,6 +15,7 @@ class RegNPC extends \sammo\Event\Action{
int $leadership,
int $strength,
int $intel,
int $officerLevel,
int $birth = 160,
int $death = 300,
$ego = null,
@@ -21,7 +23,7 @@ class RegNPC extends \sammo\Event\Action{
$text = ''
){
return (new \sammo\Scenario\GeneralBuilder(
$this->npc=(new \sammo\Scenario\GeneralBuilder(
$name,
0,
$picturePath,
@@ -29,16 +31,16 @@ class RegNPC extends \sammo\Event\Action{
))
->setCity($locatedCity)
->setStat($leadership, $strength, $intel)
->setOfficerLevel($officerLevel)
->setEgo($ego)
->setSpecialSingle($char)
->setNPCText($text?:'')
->setAffinity($affinity)
->setLifeSpan($birth, $death)
->fillRemainSpecAsZero();
->setLifeSpan($birth, $death);
}
public function run($env=null){
$result = $this->npc->build($env);
public function run(array $env){
$result = $this->npc->fillRemainSpecAsZero($env)->build($env);
return [__CLASS__, $result];
}
+5 -5
View File
@@ -3,6 +3,7 @@ namespace sammo\Event\Action;
class RegNeutralNPC extends \sammo\Event\Action{
/** @var \sammo\Scenario\GeneralBuilder */
private $npc;
public function __construct(
@@ -20,7 +21,7 @@ class RegNeutralNPC extends \sammo\Event\Action{
$char = '',
$text = ''
){
return (new \sammo\Scenario\GeneralBuilder(
$this->npc=(new \sammo\Scenario\GeneralBuilder(
$name,
0,
$picturePath,
@@ -33,12 +34,11 @@ class RegNeutralNPC extends \sammo\Event\Action{
->setNPCText($text?:'')
->setAffinity($affinity)
->setLifeSpan($birth, $death)
->setNPCType(6)
->fillRemainSpecAsZero();
->setNPCType(6);
}
public function run($env=null){
$result = $this->npc->build($env);
public function run(array $env){
$result = $this->npc->fillRemainSpecAsZero($env)->build($env);
return [__CLASS__, $result];
}
+1 -1
View File
@@ -14,7 +14,7 @@ class EventHandler{
}
public function tryRunEvent(array $env=null){
public function tryRunEvent(array $env){
$result = $this->condition->eval($env);
if(!$result['value']){
+128 -31
View File
@@ -657,29 +657,62 @@ class GeneralAI
return null;
}
$cityCandidates = [];
if($this->backupCities){
$cities = $this->backupCities;
}
else{
$cities = $this->supplyCities;
/** @var General */
$pickedGeneral = Util::choiceRandom($generalCadidates);
$minRecruitPop = $this->fullLeadership * 100 + GameConst::$minAvailableRecruitPop;
if(!$this->generalPolicy->can한계징병){
$minRecruitPop = max($minRecruitPop, $this->fullLeadership * 100 + $this->nationPolicy->minNPCRecruitCityPopulation);
}
foreach($cities as $city){
if($city['pop'] / $city['pop_max'] < $this->nationPolicy->safeRecruitCityPopulationRatio){
$recruitableCityList = [];
foreach($this->backupCities as $candidateCity){
$pop_ratio = $candidateCity['pop']/$candidateCity['pop_max'];
$cityID = $candidateCity['city'];
if($candidateCity['city'] == $this->city['city']){
continue;
}
$cityCandidates[] = $city;
if($candidateCity['pop'] < $minRecruitPop){
continue;
}
if($pop_ratio < $this->nationPolicy->safeRecruitCityPopulationRatio){
$pop_ratio /= 4;
}
$recruitableCityList[$cityID] = $pop_ratio;
}
if(!$cityCandidates){
if(!$recruitableCityList){
foreach($this->supplyCities as $candidateCity){
$pop_ratio = $candidateCity['pop']/$candidateCity['pop_max'];
$cityID = $candidateCity['city'];
if($candidateCity['city'] == $this->city['city']){
continue;
}
if($candidateCity['pop'] <= $minRecruitPop){
continue;
}
if($pop_ratio < $this->nationPolicy->safeRecruitCityPopulationRatio){
$pop_ratio /= 2;
}
if(key_exists($cityID, $this->frontCities)){
$pop_ratio / 2;
}
$recruitableCityList[$cityID] = $pop_ratio;
}
}
if(!$recruitableCityList){
return null;
}
$cmd = buildNationCommandClass('che_발령', $this->general, $this->env, $lastTurn, [
'destGeneralID'=>Util::choiceRandom($generalCadidates)->getID(),
'destCityID'=>Util::choiceRandom($cityCandidates)['city']
'destGeneralID'=>$pickedGeneral->getID(),
'destCityID'=>Util::choiceRandomUsingWeight($recruitableCityList)
]);
if(!$cmd->hasFullConditionMet()){
@@ -923,29 +956,66 @@ class GeneralAI
return null;
}
$cityCandidates = [];
if($this->backupCities){
$cities = $this->backupCities;
}
else{
$cities = $this->supplyCities;
/** @var General */
$pickedGeneral = Util::choiceRandom($generalCadidates);
$minRecruitPop = $this->fullLeadership * 100 + GameConst::$minAvailableRecruitPop;
if(!$this->generalPolicy->can한계징병){
$minRecruitPop = max($minRecruitPop, $this->fullLeadership * 100 + $this->nationPolicy->minNPCRecruitCityPopulation);
}
foreach($cities as $city){
if($city['pop'] / $city['pop_max'] < $this->nationPolicy->safeRecruitCityPopulationRatio){
$recruitableCityList = [];
foreach($this->backupCities as $candidateCity){
$pop_ratio = $candidateCity['pop']/$candidateCity['pop_max'];
$cityID = $candidateCity['city'];
if($candidateCity['city'] == $this->city['city']){
continue;
}
$cityCandidates[] = $city;
if($candidateCity['pop'] < $this->nationPolicy->minNPCRecruitCityPopulation){
continue;
}
if($candidateCity['pop'] < $minRecruitPop){
continue;
}
if($pop_ratio < $this->nationPolicy->safeRecruitCityPopulationRatio){
continue;
}
$recruitableCityList[$cityID] = $pop_ratio;
}
if(!$cityCandidates){
if(!$recruitableCityList){
foreach($this->supplyCities as $candidateCity){
$pop_ratio = $candidateCity['pop']/$candidateCity['pop_max'];
$cityID = $candidateCity['city'];
if($candidateCity['city'] == $this->city['city']){
continue;
}
if($candidateCity['pop'] < $this->nationPolicy->minNPCRecruitCityPopulation){
continue;
}
if($candidateCity['pop'] <= $minRecruitPop){
continue;
}
if($pop_ratio < $this->nationPolicy->safeRecruitCityPopulationRatio){
continue;
}
if(key_exists($cityID, $this->frontCities)){
$pop_ratio / 2;
}
$recruitableCityList[$cityID] = $pop_ratio;
}
}
if(!$recruitableCityList){
return null;
}
$cmd = buildNationCommandClass('che_발령', $this->general, $this->env, $lastTurn, [
'destGeneralID'=>Util::choiceRandom($generalCadidates)->getID(),
'destCityID'=>Util::choiceRandom($cityCandidates)['city']
'destGeneralID'=>$pickedGeneral->getID(),
'destCityID'=>Util::choiceRandomUsingWeight($recruitableCityList)
]);
if(!$cmd->hasFullConditionMet()){
@@ -2669,31 +2739,42 @@ class GeneralAI
protected function do후방워프(): ?GeneralCommand
{
$minRecruitPop = $this->fullLeadership * 100 + GameConst::$minAvailableRecruitPop;
if(!$this->generalPolicy->can한계징병){
$minRecruitPop = max($minRecruitPop, $this->fullLeadership * 100 + $this->nationPolicy->minNPCRecruitCityPopulation);
}
if (in_array($this->dipState, [self::d평화, self::d선포])) {
LogText("{$this->general->getName()}, {$this->general->getID()} 후방워프 불가: 외교 상태", $this->dipState);
return null;
}
if(!$this->generalPolicy->can징병){
LogText("{$this->general->getName()}, {$this->general->getID()} 후방워프 불가: 징병 금지", '');
return null;
}
if(!($this->genType & self::t통솔장)){
LogText("{$this->general->getName()}, {$this->general->getID()} 후방워프 불가: 통솔장", [$this->genType, $this->general->getLeadership(false)]);
return null;
}
if($this->general->getVar('crew') >= $this->nationPolicy->minWarCrew){
LogText("{$this->general->getName()}, {$this->general->getID()} 후방워프 불가: 병력 충분", [$this->general->getVar('crew'), $this->nationPolicy->minWarCrew]);
return null;
}
$city = $this->city;
if($this->generalPolicy->can한계징병){
if($city['pop'] >= $this->fullLeadership * 100 + GameConst::$minAvailableRecruitPop){
if($city['pop'] >= $minRecruitPop){
return null;
}
}
else{
if($city['pop']/$city['pop_max'] >= $this->nationPolicy->safeRecruitCityPopulationRatio){
return null;
if($city['pop'] >= $this->nationPolicy->minNPCRecruitCityPopulation && $city['pop'] >= $minRecruitPop){
LogText("{$this->general->getName()}, {$this->general->getID()} 후방워프 불가: 인구 충분", [$city['pop']/$city['pop_max'], $this->nationPolicy->safeRecruitCityPopulationRatio]);
return null;
}
}
}
@@ -2710,19 +2791,31 @@ class GeneralAI
if($pop_ratio < $this->nationPolicy->safeRecruitCityPopulationRatio){
continue;
}
if($candidateCity['pop'] < $this->nationPolicy->minNPCRecruitCityPopulation){
continue;
}
if($candidateCity['pop'] < $minRecruitPop){
continue;
}
$recruitableCityList[$cityID] = $pop_ratio;
}
if(!$recruitableCityList){
foreach($this->supplyCities as $candidateCity){
$pop_ratio = $candidateCity['pop']/$candidateCity['pop_max'];
$cityID = $candidateCity['city'];
if($candidateCity['city'] == $this->city['city']){
continue;
}
if($candidateCity['pop'] <= $this->fullLeadership * 100 + GameConst::$minAvailableRecruitPop){
if($candidateCity['pop'] < $this->nationPolicy->minNPCRecruitCityPopulation){
continue;
}
if($candidateCity['pop'] <= $minRecruitPop){
continue;
}
if($pop_ratio < $this->nationPolicy->safeRecruitCityPopulationRatio){
continue;
}
$pop_ratio = $candidateCity['pop']/$candidateCity['pop_max'];
$cityID = $candidateCity['city'];
if(key_exists($cityID, $this->frontCities)){
$recruitableCityList[$cityID] = $pop_ratio / 2;
}
@@ -2733,6 +2826,7 @@ class GeneralAI
}
if(!$recruitableCityList){
LogText("{$this->general->getName()}, {$this->general->getID()} 후방워프 불가: 배후 도시", [count($this->backupCities), count($this->supplyCities)]);
return null;
}
@@ -2744,6 +2838,7 @@ class GeneralAI
if(!$cmd->hasFullConditionMet()){
LogText("{$this->general->getName()}, {$this->general->getID()} 후방워프 불가: 조건 불충족", $cmd->getArg());
return null;
}
@@ -3364,6 +3459,7 @@ class GeneralAI
foreach($this->nationPolicy->priority as $actionName){
if(!property_exists($this->nationPolicy, 'can'.$actionName)){
trigger_error ("can{$actionName}이 없음", E_USER_NOTICE );
continue;
}
if(!$this->nationPolicy->{'can'.$actionName}){
@@ -3517,6 +3613,7 @@ class GeneralAI
foreach($this->generalPolicy->priority as $actionName){
if(!property_exists($this->generalPolicy, 'can'.$actionName)){
trigger_error ("can{$actionName}이 없음", E_USER_NOTICE );
continue;
}
if(!($this->generalPolicy->{'can'.$actionName})){
+1 -1
View File
@@ -26,7 +26,7 @@ class RandomNameGeneral extends AbsGeneralPool{
return $db->affectedRows()!=0;
}
public function giveGeneralSpec(array $pickTypeList, array $avgGen, array $env=[]){
public function giveGeneralSpec(array $pickTypeList, array $avgGen, array $env){
//do Nothing
$dexTotal = $avgGen['dex_t'];
+116 -119
View File
@@ -1,6 +1,8 @@
<?php
namespace sammo;
use sammo\Scenario\GeneralBuilder;
class Scenario{
const SCENARIO_PATH = __DIR__.'/../scenario';
@@ -37,10 +39,115 @@ class Scenario{
private $initialEvents;
private $events;
private $initBasic = false;
private $initOK = false;
private $gameConf = null;
public function generateGeneral($rawGeneral, $initFull, $npcType=2): GeneralBuilder{
while(count($rawGeneral) < 14){
$rawGeneral[] = null;
}
list(
$affinity, $name, $picturePath, $nationName, $locatedCity,
$leadership, $strength, $intel, $officerLevel, $birth, $death, $ego,
$char, $text
) = $rawGeneral;
if(key_exists($nationName, $this->nationsInv)){
$nationID = $this->nationsInv[$nationName]->getID();
}
else if(key_exists($nationName, $this->nations)){
$nationID = (int)$nationName;
}
else{
$nationID = 0;
}
$this->tmpGeneralQueue[$name] = $rawGeneral;
$obj = (new Scenario\GeneralBuilder(
$name,
false,
$picturePath,
$nationID
));
if(!$initFull){
return $obj;
}
return $obj
->setCity($locatedCity, true)
->setStat($leadership, $strength, $intel)
->setOfficerLevel($officerLevel)
->setEgo($ego)
->setSpecialSingle($char)
->setNPCText($text)
->setAffinity($affinity)
->setLifeSpan($birth, $death)
->setNPCType($npcType)
->fillRemainSpecAsZero($this->tmpEnv);
}
public function initLite(){
if($this->initOK){
return;
}
if($this->initBasic){
return;
}
$data = $this->data;
$this->tmpEnv = [
'startyear'=>$this->year,
'year'=>$this->year,
'month'=>0 //포인트
];
$neutralNation = new Scenario\Nation(0, '재야', '#000000', 0, 0);
$this->nations = [];
$this->nations[0] = $neutralNation;
$this->nationsInv = [$neutralNation->getName() => $neutralNation];
foreach (Util::array_get($data['nation'],[]) as $idx=>$rawNation) {
list($name, $color, $gold, $rice, $infoText, $tech, $type, $nationLevel, $cities) = $rawNation;
$nationID = $idx+1;
$nation = new Scenario\Nation(
$nationID,
$name,
$color,
$gold,
$rice,
$infoText,
$tech,
$type,
$nationLevel,
$cities
);
$this->nations[$nationID] = $nation;
$this->nationsInv[$nation->getName()] = $nation;
}
$this->diplomacy = Util::array_get($data['diplomacy'], []);
$this->generals = array_map(function($rawGeneral){
return $this->generateGeneral($rawGeneral, false, 2);
}, Util::array_get($data['general'], []));
$this->generalsEx = array_map(function($rawGeneral){
return $this->generateGeneral($rawGeneral, false, 2);
}, Util::array_get($data['general_ex'], []));
$this->generalsNeutral = array_map(function($rawGeneral){
return $this->generateGeneral($rawGeneral, false, 6);
}, Util::array_get($data['general_neutral'], []));
$this->initBasic = true;
}
public function initFull(){
if($this->initOK){
return;
@@ -83,125 +190,15 @@ class Scenario{
$this->generals = array_map(function($rawGeneral){
while(count($rawGeneral) < 14){
$rawGeneral[] = null;
}
list(
$affinity, $name, $picturePath, $nationName, $locatedCity,
$leadership, $strength, $intel, $officerLevel, $birth, $death, $ego,
$char, $text
) = $rawGeneral;
if(key_exists($nationName, $this->nationsInv)){
$nationID = $this->nationsInv[$nationName]->getID();
}
else if(key_exists($nationName, $this->nations)){
$nationID = (int)$nationName;
}
else{
$nationID = 0;
}
$this->tmpGeneralQueue[$name] = $rawGeneral;
return (new Scenario\GeneralBuilder(
$name,
false,
$picturePath,
$nationID
))
->setCity($locatedCity)
->setStat($leadership, $strength, $intel)
->setOfficerLevel($officerLevel)
->setEgo($ego)
->setSpecialSingle($char)
->setNPCText($text)
->setAffinity($affinity)
->setLifeSpan($birth, $death)
->fillRemainSpecAsZero($this->tmpEnv);
return $this->generateGeneral($rawGeneral, true, 2);
}, Util::array_get($data['general'], []));
$this->generalsEx = array_map(function($rawGeneral){
while(count($rawGeneral) < 14){
$rawGeneral[] = null;
}
list(
$affinity, $name, $picturePath, $nationName, $locatedCity,
$leadership, $strength, $intel, $officerLevel, $birth, $death, $ego,
$char, $text
) = $rawGeneral;
if(key_exists($nationName, $this->nationsInv)){
$nationID = $this->nationsInv[$nationName]->getID();
}
else if(key_exists($nationName, $this->nations)){
$nationID = (int)$nationName;
}
else{
$nationID = 0;
}
$this->tmpGeneralQueue[$name] = $rawGeneral;
return (new Scenario\GeneralBuilder(
$name,
false,
$picturePath,
$nationID
))
->setCity($locatedCity, true)
->setStat($leadership, $strength, $intel)
->setOfficerLevel($officerLevel)
->setEgo($ego)
->setSpecialSingle($char)
->setNPCText($text)
->setAffinity($affinity)
->setLifeSpan($birth, $death)
->fillRemainSpecAsZero($this->tmpEnv);
return $this->generateGeneral($rawGeneral, true, 2);
}, Util::array_get($data['general_ex'], []));
$this->generalsNeutral = array_map(function($rawGeneral){
while(count($rawGeneral) < 14){
$rawGeneral[] = null;
}
list(
$affinity, $name, $picturePath, $nationName, $locatedCity,
$leadership, $strength, $intel, $officerLevel, $birth, $death, $ego,
$char, $text
) = $rawGeneral;
if(key_exists($nationName, $this->nationsInv)){
$nationID = $this->nationsInv[$nationName]->getID();
}
else if(key_exists($nationName, $this->nations)){
$nationID = (int)$nationName;
}
else{
$nationID = 0;
}
$this->tmpGeneralQueue[$name] = $rawGeneral;
return (new Scenario\GeneralBuilder(
$name,
false,
$picturePath,
$nationID
))
->setCity($locatedCity, true)
->setStat($leadership, $strength, $intel)
->setOfficerLevel($officerLevel)
->setEgo($ego)
->setSpecialSingle($char)
->setNPCText($text)
->setAffinity($affinity)
->setLifeSpan($birth, $death)
->setNPCType(6)
->fillRemainSpecAsZero($this->tmpEnv);
return $this->generateGeneral($rawGeneral, true, 6);
}, Util::array_get($data['general_neutral'], []));
$this->initialEvents = array_map(function($rawEvent){
@@ -293,22 +290,22 @@ class Scenario{
}
public function getNPC(){
$this->initFull();
$this->initLite();
return $this->generals;
}
public function getNPCex(){
$this->initFull();
$this->initLite();
return $this->generalsEx;
}
public function getNPCneutral(){
$this->initFull();
$this->initLite();
return $this->generalsNeutral;
}
public function getNation(){
$this->initFull();
$this->initLite();
return $this->nations;
}
@@ -321,7 +318,7 @@ class Scenario{
}
public function getScenarioBrief(){
$this->initFull();
$this->initLite();
$nations = [];
$nationGeneralCnt = [];
@@ -485,7 +482,7 @@ class Scenario{
copy("$unitPath/$unitSet.php", $path.'/GameUnitConst.php');
}
public function build($env=[]){
public function build($env){
$db = DB::db();
getGeneralPoolClass(GameConst::$targetGeneralPool)::initPool($db);
+3 -3
View File
@@ -337,7 +337,7 @@ class GeneralBuilder{
return $this;
}
public function fillRemainSpecAsZero(array $env=[]):self{
public function fillRemainSpecAsZero(array $env):self{
if($this->leadership===null){
throw new \RuntimeException('stat이 설정되어 있지 않음');
}
@@ -390,7 +390,7 @@ class GeneralBuilder{
return $this;
}
public function fillRemainSpecAsRandom(array $pickTypeList, array $avgGen, array $env=[]):self{
public function fillRemainSpecAsRandom(array $pickTypeList, array $avgGen, array $env):self{
$isFictionMode = (Util::array_get($env['fiction'], 0)!=0);
@@ -532,7 +532,7 @@ class GeneralBuilder{
return $this->death;
}
public function build($env=[]){
public function build($env){
//scenario에 life==1인 경우 수명 제한이 없어지는 모양.
+2 -2
View File
@@ -64,7 +64,7 @@ class Nation{
return $this->name;
}
public function build($env=[]){
public function build($env){
//NOTE: NPC의 숫자는 아직 확정된 것이 아니다.
$cities = array_map(function($cityName){
return \sammo\CityHelper::getCityByName($cityName)['id'];
@@ -147,7 +147,7 @@ class Nation{
$this->generals[] = $general;
}
public function postBuild($env=[]){
public function postBuild($env){
$npc_cnt = count($this->generals);
$db = DB::db();
+12 -3
View File
@@ -186,7 +186,7 @@ class TurnExecutionHelper
$general->setVar('killturn', ($general->getVar('deadyear') - $gameStor->year) * 12);
$general->setVar('npc', $general->getVar('npc_org'));
$general->setVar('owner', 1);
$general->setVar('owner', 0);
$general->setVar('defence_train', 80);
$general->setVar('owner_name', null);
}
@@ -321,7 +321,7 @@ class TurnExecutionHelper
return;
}
if ($gameStor->isunited == 2) {
if ($gameStor->isunited == 2 || $gameStor->isunited == 3) {
//천통시에는 동결
return;
}
@@ -407,13 +407,22 @@ class TurnExecutionHelper
}
// 이벤트 핸들러 동작
$e_env = null;
foreach (DB::db()->query('SELECT * from event') as $rawEvent) {
if($e_env === null){
$e_env = $gameStor->getAll(false);
}
$eventID = $rawEvent['id'];
$cond = Json::decode($rawEvent['condition']);
$action = Json::decode($rawEvent['action']);
$event = new Event\EventHandler($cond, $action);
$e_env['currentEventID'] = $eventID;
$event->tryRunEvent(['currentEventID'=>$eventID] + $gameStor->getAll(true));
$event->tryRunEvent($e_env);
}
if($e_env !== null){
$gameStor->resetCache(true);
}
postUpdateMonthly();
+3
View File
@@ -270,6 +270,9 @@ class WarUnitGeneral extends WarUnit{
if($this->hasActivatedSkillOnLog('부상무효')){
return false;
}
if($this->hasActivatedSkillOnLog('퇴각부상무효')){
return false;
}
if(!Util::randBool(0.05)){
return false;
}
@@ -10,13 +10,19 @@ use sammo\ObjectTrigger;
class che_반계시도 extends BaseWarUnitTrigger{
protected $priority = ObjectTrigger::PRIORITY_BODY + 300;
protected $prob;
public function __construct(WarUnit $unit, int $raiseType = 0, float $prob = 0.4){
$this->object = $unit;
$this->prob = $prob;
}
protected function actionWar(WarUnit $self, WarUnit $oppose, array &$selfEnv, array &$opposeEnv):bool{
if(!$oppose->hasActivatedSkill('계략')){
return true;
}
if(!Util::randBool(0.4)){
if(!Util::randBool($this->prob)){
return true;
}
@@ -0,0 +1,19 @@
<?php
namespace sammo\WarUnitTrigger;
use sammo\BaseWarUnitTrigger;
use sammo\WarUnitGeneral;
use sammo\WarUnitCity;
use sammo\WarUnit;
use sammo\GameUnitDetail;
use sammo\ObjectTrigger;
class che_퇴각부상무효 extends BaseWarUnitTrigger{
protected $priority = ObjectTrigger::PRIORITY_BEGIN + 300;
protected function actionWar(WarUnit $self, WarUnit $oppose, array &$selfEnv, array &$opposeEnv):bool{
assert($self instanceof WarUnitGeneral, 'General만 발동 가능');
$self->activateSkill('퇴각부상무효');
return true;
}
}
+1 -1
View File
@@ -16,7 +16,7 @@
"events":[
[
["Date", "==", null, 12],
["CreateManyNPC", 10],
["CreateManyNPC", 30],
["DeleteEvent"]
]
]
+1 -1
View File
@@ -60,7 +60,7 @@
"events":[
[
["Date", "==", null, 12],
["CreateManyNPC", 10],
["CreateManyNPC", 30],
["DeleteEvent"]
],
[
-2
View File
@@ -4,8 +4,6 @@ namespace sammo;
require(__DIR__ . '/vendor/autoload.php');
WebUtil::requireAJAX();
function getVersion($target = null)
{
if ($target) {
+12 -6
View File
@@ -84,7 +84,7 @@ var serverReservedTemplate = "\
</td>\
";
$(function() {
$(function () {
$("#btn_logout").click(Entrance_Logout);
Entrance_UpdateServer();
});
@@ -94,7 +94,7 @@ function Entrance_UpdateServer() {
type: 'post',
url: "j_server_get_status.php",
dataType: 'json',
}).then(function(response) {
}).then(function (response) {
if (response.result == "SUCCESS") {
Entrance_drawServerList(response.server);
}
@@ -104,7 +104,7 @@ function Entrance_UpdateServer() {
function Entrance_drawServerList(serverInfos) {
var $serverList = $('#server_list');
var now = moment().format('YYYY-MM-DD HH:mm:ss');
$.each(serverInfos, function(idx, serverInfo) {
$.each(serverInfos, function (idx, serverInfo) {
var $serverHtml = $(TemplateEngine(serverListTemplate, serverInfo));
$serverList.append($serverHtml);
if (!serverInfo.exists) {
@@ -114,7 +114,7 @@ function Entrance_drawServerList(serverInfos) {
var serverPath = "../" + serverInfo.name;
$.getJSON("../" + serverInfo.name + '/j_server_basic_info.php', {}, function(result) {
$.getJSON("../" + serverInfo.name + '/j_server_basic_info.php', {}, function (result) {
if (result.reserved) {
$serverHtml.find('.server_down').detach();
$serverHtml.append(
@@ -134,7 +134,13 @@ function Entrance_drawServerList(serverInfos) {
$serverHtml.find('.server_down').detach();
var serverTime = '%s ~ %s'.format(game.startFrom)
if (game.isUnited == 2) {
if (game.isUnited == 3) {
$serverHtml.find('.n_country').html('§이벤트 종료§');
$serverHtml.find('.server_date').html('{0} <br>~ {1}'.format(game.starttime, game.turntime));
} else if (game.isUnited == 1) {
$serverHtml.find('.n_country').html('§이벤트 진행중§');
$serverHtml.find('.server_date').html('{0} ~'.format(game.starttime));
} else if (game.isUnited == 2) {
$serverHtml.find('.n_country').html('§천하통일§');
$serverHtml.find('.server_date').html('{0} <br>~ {1}'.format(game.starttime, game.turntime));
} else if (game.opentime <= now) {
@@ -187,7 +193,7 @@ function Entrance_Logout() {
type: 'post',
url: "j_logout.php",
dataType: 'json',
}).then(function(response) {
}).then(function (response) {
if (response.result) {
location.href = "../";
} else {