전투 시뮬레이터를 포함한 코드 적용
This commit is contained in:
@@ -0,0 +1,132 @@
|
||||
//download.js v3.0, by dandavis; 2008-2014. [CCBY2] see http://danml.com/download.html for tests/usage
|
||||
// v1 landed a FF+Chrome compat way of downloading strings to local un-named files, upgraded to use a hidden frame and optional mime
|
||||
// v2 added named files via a[download], msSaveBlob, IE (10+) support, and window.URL support for larger+faster saves than dataURLs
|
||||
// v3 added dataURL and Blob Input, bind-toggle arity, and legacy dataURL fallback was improved with force-download mime and base64 support
|
||||
|
||||
// data can be a string, Blob, File, or dataURL
|
||||
|
||||
|
||||
|
||||
|
||||
function download(data, strFileName, strMimeType) {
|
||||
|
||||
var self = window, // this script is only for browsers anyway...
|
||||
u = "application/octet-stream", // this default mime also triggers iframe downloads
|
||||
m = strMimeType || u,
|
||||
x = data,
|
||||
D = document,
|
||||
a = D.createElement("a"),
|
||||
z = function(a){return String(a);},
|
||||
|
||||
|
||||
B = self.Blob || self.MozBlob || self.WebKitBlob || z,
|
||||
BB = self.MSBlobBuilder || self.WebKitBlobBuilder || self.BlobBuilder,
|
||||
fn = strFileName || "download",
|
||||
blob,
|
||||
b,
|
||||
ua,
|
||||
fr;
|
||||
|
||||
//if(typeof B.bind === 'function' ){ B=B.bind(self); }
|
||||
|
||||
if(String(this)==="true"){ //reverse arguments, allowing download.bind(true, "text/xml", "export.xml") to act as a callback
|
||||
x=[x, m];
|
||||
m=x[0];
|
||||
x=x[1];
|
||||
}
|
||||
|
||||
|
||||
|
||||
//go ahead and download dataURLs right away
|
||||
if(String(x).match(/^data\:[\w+\-]+\/[\w+\-]+[,;]/)){
|
||||
return navigator.msSaveBlob ? // IE10 can't do a[download], only Blobs:
|
||||
navigator.msSaveBlob(d2b(x), fn) :
|
||||
saver(x) ; // everyone else can save dataURLs un-processed
|
||||
}//end if dataURL passed?
|
||||
|
||||
try{
|
||||
|
||||
blob = x instanceof B ?
|
||||
x :
|
||||
new B([x], {type: m}) ;
|
||||
}catch(y){
|
||||
if(BB){
|
||||
b = new BB();
|
||||
b.append([x]);
|
||||
blob = b.getBlob(m); // the blob
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
function d2b(u) {
|
||||
var p= u.split(/[:;,]/),
|
||||
t= p[1],
|
||||
dec= p[2] == "base64" ? atob : decodeURIComponent,
|
||||
bin= dec(p.pop()),
|
||||
mx= bin.length,
|
||||
i= 0,
|
||||
uia= new Uint8Array(mx);
|
||||
|
||||
for(i;i<mx;++i) uia[i]= bin.charCodeAt(i);
|
||||
|
||||
return new B([uia], {type: t});
|
||||
}
|
||||
|
||||
function saver(url, winMode){
|
||||
|
||||
|
||||
if ('download' in a) { //html5 A[download]
|
||||
a.href = url;
|
||||
a.setAttribute("download", fn);
|
||||
a.innerHTML = "downloading...";
|
||||
D.body.appendChild(a);
|
||||
setTimeout(function() {
|
||||
a.click();
|
||||
D.body.removeChild(a);
|
||||
if(winMode===true){setTimeout(function(){ self.URL.revokeObjectURL(a.href);}, 250 );}
|
||||
}, 66);
|
||||
return true;
|
||||
}
|
||||
|
||||
//do iframe dataURL download (old ch+FF):
|
||||
var f = D.createElement("iframe");
|
||||
D.body.appendChild(f);
|
||||
if(!winMode){ // force a mime that will download:
|
||||
url="data:"+url.replace(/^data:([\w\/\-\+]+)/, u);
|
||||
}
|
||||
|
||||
|
||||
f.src = url;
|
||||
setTimeout(function(){ D.body.removeChild(f); }, 333);
|
||||
|
||||
}//end saver
|
||||
|
||||
|
||||
if (navigator.msSaveBlob) { // IE10+ : (has Blob, but not a[download] or URL)
|
||||
return navigator.msSaveBlob(blob, fn);
|
||||
}
|
||||
|
||||
if(self.URL){ // simple fast and modern way using Blob and URL:
|
||||
saver(self.URL.createObjectURL(blob), true);
|
||||
}else{
|
||||
// handle non-Blob()+non-URL browsers:
|
||||
if(typeof blob === "string" || blob.constructor===z ){
|
||||
try{
|
||||
return saver( "data:" + m + ";base64," + self.btoa(blob) );
|
||||
}catch(y){
|
||||
return saver( "data:" + m + "," + encodeURIComponent(blob) );
|
||||
}
|
||||
}
|
||||
|
||||
// Blob but not URL:
|
||||
fr=new FileReader();
|
||||
fr.onload=function(e){
|
||||
saver(this.result);
|
||||
};
|
||||
fr.readAsDataURL(blob);
|
||||
}
|
||||
return true;
|
||||
} /* end download() */
|
||||
|
||||
Vendored
+1
File diff suppressed because one or more lines are too long
@@ -452,15 +452,7 @@ echo "
|
||||
</tr>
|
||||
";
|
||||
|
||||
$citylevel = [];
|
||||
$citylevel[1] = "수";
|
||||
$citylevel[2] = "진";
|
||||
$citylevel[3] = "관";
|
||||
$citylevel[4] = "이";
|
||||
$citylevel[5] = "소";
|
||||
$citylevel[6] = "중";
|
||||
$citylevel[7] = "대";
|
||||
$citylevel[8] = "특";
|
||||
$citylevel = getCityLevelList();
|
||||
|
||||
$query = "select city,name,gen1,gen2,gen3,level,region,gen1set,gen2set,gen3set from city where nation='{$nation['nation']}' order by region,level desc,binary(name)"; // 도시 이름 목록
|
||||
$cityresult = MYDB_query($query, $connect) or Error(__LINE__.MYDB_error($connect),"");
|
||||
|
||||
@@ -0,0 +1,473 @@
|
||||
<?php
|
||||
namespace sammo;
|
||||
|
||||
include "lib.php";
|
||||
include "func.php";
|
||||
|
||||
$session = Session::requireLogin()->setReadOnly();
|
||||
$db = DB::db();
|
||||
$gameStor = KVStorage::getStorage($db, 'game_env');
|
||||
|
||||
$startYear = $gameStor->getValue('startyear');
|
||||
|
||||
?>
|
||||
<!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=1100" />
|
||||
<?=WebUtil::printCSS('../e_lib/bootstrap.min.css')?>
|
||||
<?=WebUtil::printCSS('../d_shared/common.css')?>
|
||||
<?=WebUtil::printCSS('css/common.css')?>
|
||||
<?=WebUtil::printCSS('css/battle_simulator.css')?>
|
||||
<?=WebUtil::printJS('../d_shared/common_path.js')?>
|
||||
<?=WebUtil::printJS('../e_lib/jquery-3.3.1.min.js')?>
|
||||
<?=WebUtil::printJS('../e_lib/moment.min.js')?>
|
||||
<?=WebUtil::printJS('../e_lib/bootstrap.bundle.min.js')?>
|
||||
<?=WebUtil::printJS('../e_lib/download2.js')?>
|
||||
<?=WebUtil::printJS('js/common.js')?>
|
||||
<?=WebUtil::printJS('js/battle_simulator.js')?>
|
||||
</head>
|
||||
<body>
|
||||
<div id="container">
|
||||
<div class="card mb-3">
|
||||
<div class="card-header">
|
||||
전역 설정
|
||||
</div>
|
||||
<div class="card-body dragpad_battle">
|
||||
<div class="row">
|
||||
<div class="col-sm-6">
|
||||
<div class="input-group">
|
||||
<input type="number" class="form-control" aria-describedby="text_year" value="<?=$startYear?>" disabled>
|
||||
<div class="input-group-append">
|
||||
<span class="input-group-text">년 시작</span>
|
||||
</div>
|
||||
<input type="number" class="form-control" id="year" value="<?=$startYear+3?>" min="<?=$startYear?>">
|
||||
<div class="input-group-append">
|
||||
<span class="input-group-text">년</span>
|
||||
</div>
|
||||
<input type="number" class="form-control" id="month" value="1" min="1" max="12">
|
||||
<div class="input-group-append">
|
||||
<span class="input-group-text">월</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-sm-6">
|
||||
<div class="btn-toolbar" role="toolbar">
|
||||
<div class="input-group mr-2" role="group">
|
||||
<div class="input-group-prepend">
|
||||
<span class="input-group-text">반복 횟수</span>
|
||||
</div>
|
||||
<select class="custom-select" id="repeat_cnt">
|
||||
<option value="1">1회 (로그 표기)</option>
|
||||
<option value="1000">1000회 (요약 표기)</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="btn-group mr-2" role="group">
|
||||
<button type="button" class="btn btn-danger btn-begin_battle">전투</button>
|
||||
</div>
|
||||
<div class="btn-group mr-2" role="group">
|
||||
<button type="button" class="btn btn-info btn-battle-save">모두 저장</button>
|
||||
<input type="file" class="form_load_battle_file" accept=".json" style="display: none;" />
|
||||
<button type="button" class="btn btn-primary btn-battle-load">모두 불러오기</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-sm">
|
||||
<div class="card mb-2 attacker_nation">
|
||||
<div class="card-header">
|
||||
출병국 설정
|
||||
</div>
|
||||
<div class="card-body nation_detail dragpad_battle">
|
||||
<div class="input-group mb-1">
|
||||
<div class="input-group-prepend">
|
||||
<span class="input-group-text">국가 성향</span>
|
||||
</div>
|
||||
<select class="custom-select form_nation_type" style="width:25ch;">
|
||||
<?php foreach(getNationTypeList() as $typeID => [$name,$pros,$cons]): ?>
|
||||
<option value="<?=$typeID?>"><?=$name?> (<?=$pros?>, <?=$cons?>)</option>
|
||||
<?php endforeach; ?>
|
||||
</select>
|
||||
<div class="input-group-prepend">
|
||||
<span class="input-group-text">기술</span>
|
||||
</div>
|
||||
<input type="number" class="form-control form_tech" value="1" min="0" max="12">
|
||||
<div class="input-group-append">
|
||||
<span class="input-group-text">등급</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="input-group mb-3">
|
||||
<div class="input-group-prepend">
|
||||
<span class="input-group-text">국가 규모</span>
|
||||
</div>
|
||||
<select class="custom-select form_nation_level">
|
||||
<?php foreach(getNationLevelList() as $nationLevel => [$name,$chiefCnt,$cityCnt]): ?>
|
||||
<option value="<?=$nationLevel?>"><?=$name?></option>
|
||||
<?php endforeach; ?>
|
||||
</select>
|
||||
<div class="input-group-prepend">
|
||||
<span class="input-group-text">도시 규모</span>
|
||||
</div>
|
||||
<select class="custom-select form_city_level">
|
||||
<?php foreach(getCityLevelList() as $levelID => $name): ?>
|
||||
<option value="<?=$levelID?>"><?=$name?></option>
|
||||
<?php endforeach; ?>
|
||||
</select>
|
||||
<div class="input-group-prepend">
|
||||
<span class="input-group-text">수도</span>
|
||||
</div>
|
||||
<div class="input-group-append btn-group btn-group-toggle" data-toggle="buttons">
|
||||
<label class="btn btn-secondary">
|
||||
<input type="radio" name="is_attacker_capital" class="form_is_capital" value="1" autocomplete="off">Y
|
||||
</label>
|
||||
<label class="btn btn-secondary active">
|
||||
<input type="radio" name="is_attacker_capital" class="form_is_capital" value="2" autocomplete="off" checked>N
|
||||
</label>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<div class="input-group mb-1">
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card mb-2 attacker_form general_form" data-general_no='1'>
|
||||
<div class="card-header">
|
||||
<div class="float-sm-left" style="line-height:25px;">출병자 설정</div>
|
||||
<div class="float-sm-right btn-toolbar" role="toolbar">
|
||||
<div class="btn-group btn-group-sm mr-2" role="group">
|
||||
<button type="button" class="btn btn-info btn-general-save">저장</button>
|
||||
<input type="file" class="form_load_general_file" accept=".json" style="display: none;" />
|
||||
<button type="button" class="btn btn-primary btn-general-load">불러오기</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div><!-- <div class="col-sm"> -->
|
||||
<div class="col-sm defender-column">
|
||||
<div class="card mb-2 defender_nation">
|
||||
<div class="card-header">
|
||||
수비국 설정
|
||||
</div>
|
||||
<div class="card-body dragpad_battle">
|
||||
<div class="input-group mb-1">
|
||||
<div class="input-group-prepend">
|
||||
<span class="input-group-text">국가 성향</span>
|
||||
</div>
|
||||
<select class="custom-select form_nation_type" style="width:25ch;">
|
||||
<?php foreach(getNationTypeList() as $typeID => [$name,$pros,$cons]): ?>
|
||||
<option value="<?=$typeID?>"><?=$name?> (<?=$pros?>, <?=$cons?>)</option>
|
||||
<?php endforeach; ?>
|
||||
</select>
|
||||
<div class="input-group-prepend">
|
||||
<span class="input-group-text">기술</span>
|
||||
</div>
|
||||
<input type="number" class="form-control form_tech" value="1" min="0" max="12">
|
||||
<div class="input-group-append">
|
||||
<span class="input-group-text">등급</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="input-group mb-3">
|
||||
<div class="input-group-prepend">
|
||||
<span class="input-group-text">국가 규모</span>
|
||||
</div>
|
||||
<select class="custom-select form_nation_level">
|
||||
<?php foreach(getNationLevelList() as $nationLevel => [$name,$chiefCnt,$cityCnt]): ?>
|
||||
<option value="<?=$nationLevel?>"><?=$name?></option>
|
||||
<?php endforeach; ?>
|
||||
</select>
|
||||
<div class="input-group-prepend">
|
||||
<span class="input-group-text">도시 규모</span>
|
||||
</div>
|
||||
<select class="custom-select form_city_level">
|
||||
<?php foreach(getCityLevelList() as $levelID => $name): ?>
|
||||
<option value="<?=$levelID?>"><?=$name?></option>
|
||||
<?php endforeach; ?>
|
||||
</select>
|
||||
<div class="input-group-prepend">
|
||||
<span class="input-group-text">수도</span>
|
||||
</div>
|
||||
<div class="input-group-append btn-group btn-group-toggle" data-toggle="buttons">
|
||||
<label class="btn btn-secondary">
|
||||
<input type="radio" name="is_defender_capital" class="form_is_capital" value="1" autocomplete="off">Y
|
||||
</label>
|
||||
<label class="btn btn-secondary active">
|
||||
<input type="radio" name="is_defender_capital" class="form_is_capital" value="0" autocomplete="off" checked>N
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="input-group mb-1">
|
||||
<div class="input-group-prepend">
|
||||
<span class="input-group-text">수비</span>
|
||||
</div>
|
||||
<input type="number" class="form-control form_def" id="city_def" value="1000" min="10" step="10">
|
||||
<div class="input-group-prepend">
|
||||
<span class="input-group-text">성벽</span>
|
||||
</div>
|
||||
<input type="number" class="form-control form_wall" id="city_wall" value="1000" min="0" step="10">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card mb-2 defender_add_form">
|
||||
<div class="card-header">
|
||||
<div class="float-sm-left" style="line-height:25px;">수비자 설정</div>
|
||||
<div class="float-sm-right btn-toolbar" role="toolbar">
|
||||
<div class="btn-group btn-group-sm mr-2" role="group">
|
||||
<button type="button" class="btn btn-dark btn-reorder_defender">수비 순서대로 정렬</button>
|
||||
</div>
|
||||
<div class="btn-group btn-group-sm" role="group">
|
||||
<button type="button" class="btn btn-success add-defender">추가</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card mb-2 form_sample">
|
||||
<div class="card-header">
|
||||
<div class="float-sm-left" style="line-height:25px;">수비자 설정</div>
|
||||
<div class="float-sm-right btn-toolbar" role="toolbar">
|
||||
<div class="btn-group btn-group-sm mr-2" role="group">
|
||||
<button type="button" class="btn btn-info btn-general-save">저장</button>
|
||||
<input type="file" class="form_load_general_file" accept=".json" style="display: none;" />
|
||||
<button type="button" class="btn btn-primary btn-general-load">불러오기</button>
|
||||
</div>
|
||||
<div class="btn-group btn-group-sm" role="group">
|
||||
<button type="button" class="btn btn-warning copy-defender">복제</button>
|
||||
<button type="button" class="btn btn-danger delete-defender">제거</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-body general_detail">
|
||||
<div class="input-group mb-3">
|
||||
<div class="input-group-prepend">
|
||||
<span class="input-group-text">이름</span>
|
||||
</div>
|
||||
<input type="text" class="form-control form_general_name" value="무명" style="width:15ch;">
|
||||
<div class="input-group-prepend">
|
||||
<span class="input-group-text">직위</span>
|
||||
</div>
|
||||
<select class="custom-select form_general_level" style="width:8ch;">
|
||||
<option value="1">일반</option>
|
||||
<option value="4">태수</option>
|
||||
<option value="3">군사</option>
|
||||
<option value="2">시중</option>
|
||||
<option value="10">무장 수뇌</option>
|
||||
<option value="9">지장 수뇌</option>
|
||||
<option value="11">참모</option>
|
||||
<option value="12">군주</option>
|
||||
</select>
|
||||
<div class="input-group-prepend">
|
||||
<span class="input-group-text">Level</span>
|
||||
</div>
|
||||
<input type="number" class="form-control form_exp_level" value="20" min="0" max="300" step="1">
|
||||
|
||||
</div>
|
||||
<div class="input-group mb-1">
|
||||
<div class="input-group-prepend">
|
||||
<span class="input-group-text">통솔</span>
|
||||
</div>
|
||||
<input type="number" class="form-control form_leadership" value="50" min="1" max="300" step="1">
|
||||
<div class="input-group-prepend">
|
||||
<span class="input-group-text">무력</span>
|
||||
</div>
|
||||
<input type="number" class="form-control form_power" value="50" min="1" max="300" step="1">
|
||||
<div class="input-group-prepend">
|
||||
<span class="input-group-text">지력</span>
|
||||
</div>
|
||||
<input type="number" class="form-control form_intel" value="50" min="1" max="300" step="1">
|
||||
</div>
|
||||
<div class="input-group mb-1">
|
||||
<div class="input-group-prepend">
|
||||
<span class="input-group-text">명마</span>
|
||||
</div>
|
||||
<select class="custom-select form_general_horse">
|
||||
<?php foreach(range(0, 26) as $horseID): ?>
|
||||
<option value="<?=$horseID?>"><?=getHorseName($horseID)?></option>
|
||||
<?php endforeach; ?>
|
||||
</select>
|
||||
<div class="input-group-prepend">
|
||||
<span class="input-group-text">무기</span>
|
||||
</div>
|
||||
<select class="custom-select form_general_weap">
|
||||
<?php foreach(range(0, 26) as $weapID): ?>
|
||||
<option value="<?=$weapID?>"><?=getWeapName($weapID)?></option>
|
||||
<?php endforeach; ?>
|
||||
</select>
|
||||
<div class="input-group-prepend">
|
||||
<span class="input-group-text">서적</span>
|
||||
</div>
|
||||
<select class="custom-select form_general_book">
|
||||
<?php foreach(range(0, 26) as $bookID): ?>
|
||||
<option value="<?=$bookID?>"><?=getBookName($bookID)?></option>
|
||||
<?php endforeach; ?>
|
||||
</select>
|
||||
</div>
|
||||
<div class="input-group mb-3">
|
||||
<div class="input-group-prepend">
|
||||
<span class="input-group-text">부상</span>
|
||||
</div>
|
||||
<input type="number" class="form-control form_injury" value="0" min="0" max="80" step="1">
|
||||
<div class="input-group-append">
|
||||
<span class="input-group-text">%(<span class="injury_helptext">건강</span>)</span>
|
||||
</div>
|
||||
<div class="input-group-prepend">
|
||||
<span class="input-group-text">군량</span>
|
||||
</div>
|
||||
<input type="number" class="form-control form_rice" value="5000" min="50" max="40000" step="50">
|
||||
<div class="input-group-prepend">
|
||||
<span class="input-group-text">도구</span>
|
||||
</div>
|
||||
<select class="custom-select form_general_item">
|
||||
<?php foreach(range(0, 26) as $bookID): ?>
|
||||
<option value="<?=$bookID?>"><?=getItemName($bookID)?></option>
|
||||
<?php endforeach; ?>
|
||||
</select>
|
||||
</div>
|
||||
<div class="input-group mb-1">
|
||||
<div class="input-group-prepend">
|
||||
<span class="input-group-text">병종</span>
|
||||
</div>
|
||||
<select class="custom-select form_crewtype">
|
||||
<?php foreach(GameUnitConst::all() as $crewTypeID => $crewType): ?>
|
||||
<?php if($crewTypeID < 0){ continue; } ?>
|
||||
<option value="<?=$crewTypeID?>"><?=$crewType->name?></option>
|
||||
<?php endforeach; ?>
|
||||
</select>
|
||||
<div class="input-group-prepend">
|
||||
<span class="input-group-text">병사</span>
|
||||
</div>
|
||||
<input type="number" class="form-control form_crew" value="7000" min="100" step="100">
|
||||
<div class="input-group-prepend">
|
||||
<span class="input-group-text">성격</span>
|
||||
</div>
|
||||
<select class="custom-select form_general_character">
|
||||
<?php foreach(getCharacterList() as $characterID => [$name,$info]): ?>
|
||||
<option value="<?=$characterID?>"><?=$name?></option>
|
||||
<?php endforeach; ?>
|
||||
</select>
|
||||
</div>
|
||||
<div class="input-group mb-3">
|
||||
<div class="input-group-prepend">
|
||||
<span class="input-group-text">훈련</span>
|
||||
</div>
|
||||
<input type="number" class="form-control form_train" value="100" min="40" max="<?=GameConst::$maxTrainByWar?>" step="1">
|
||||
<div class="input-group-prepend">
|
||||
<span class="input-group-text">사기</span>
|
||||
</div>
|
||||
<input type="number" class="form-control form_atmos" value="100" min="40" max="<?=GameConst::$maxAtmosByWar?>" step="1">
|
||||
<div class="input-group-prepend">
|
||||
<span class="input-group-text">전특</span>
|
||||
</div>
|
||||
<select class="custom-select form_general_special_war">
|
||||
<option value="0">-</option>
|
||||
<?php foreach(SpecialityConst::WAR as $specialWarID => [$name,$buff,$cond]): ?>
|
||||
<option value="<?=$specialWarID?>"><?=$name?></option>
|
||||
<?php endforeach; ?>
|
||||
</select>
|
||||
</div>
|
||||
<div class="input-group mb-1">
|
||||
<div class="input-group-prepend">
|
||||
<span class="input-group-text">보병숙련</span>
|
||||
</div>
|
||||
<select class="custom-select form_dex0">
|
||||
<?php foreach(getDexLevelList() as $dexLevel => [$dexAmount, $color, $name]): ?>
|
||||
<option value="<?=$dexAmount?>"><?="{$name} (".number_format($dexAmount).")"?></option>
|
||||
<?php endforeach; ?>
|
||||
</select>
|
||||
<div class="input-group-prepend">
|
||||
<span class="input-group-text">궁병숙련</span>
|
||||
</div>
|
||||
<select class="custom-select form_dex10">
|
||||
<?php foreach(getDexLevelList() as $dexLevel => [$dexAmount, $color, $name]): ?>
|
||||
<option value="<?=$dexAmount?>"><?="{$name} (".number_format($dexAmount).")"?></option>
|
||||
<?php endforeach; ?>
|
||||
</select>
|
||||
<div class="input-group-prepend">
|
||||
<span class="input-group-text">기병숙련</span>
|
||||
</div>
|
||||
<select class="custom-select form_dex20">
|
||||
<?php foreach(getDexLevelList() as $dexLevel => [$dexAmount, $color, $name]): ?>
|
||||
<option value="<?=$dexAmount?>"><?="{$name} (".number_format($dexAmount).")"?></option>
|
||||
<?php endforeach; ?>
|
||||
</select>
|
||||
</div>
|
||||
<div class="input-group mb-1">
|
||||
<div class="input-group-prepend">
|
||||
<span class="input-group-text">귀병숙련</span>
|
||||
</div>
|
||||
<select class="custom-select form_dex30">
|
||||
<?php foreach(getDexLevelList() as $dexLevel => [$dexAmount, $color, $name]): ?>
|
||||
<option value="<?=$dexAmount?>"><?="{$name} (".number_format($dexAmount).")"?></option>
|
||||
<?php endforeach; ?>
|
||||
</select>
|
||||
<div class="input-group-prepend">
|
||||
<span class="input-group-text">차병숙련</span>
|
||||
</div>
|
||||
<select class="custom-select form_dex40">
|
||||
<?php foreach(getDexLevelList() as $dexLevel => [$dexAmount, $color, $name]): ?>
|
||||
<option value="<?=$dexAmount?>"><?="{$name} (".number_format($dexAmount).")"?></option>
|
||||
<?php endforeach; ?>
|
||||
</select>
|
||||
<div class="input-group-prepend only_defender">
|
||||
<span class="input-group-text">수비여부</span>
|
||||
</div>
|
||||
<select class="custom-select form_defend_mode only_defender">
|
||||
<option value="2">훈사 80</option>
|
||||
<option value="3">훈사 60</option>
|
||||
<option value="0">안함</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
</div><!-- <div class="col-sm"> -->
|
||||
</div>
|
||||
<div class="card mb-3">
|
||||
<div class="card-header">
|
||||
전투 요약
|
||||
</div>
|
||||
<table class="table">
|
||||
<tbody id="battle_result_summary">
|
||||
<tr><th style='width:18ch;'>전투 일시</th><td id='result_datetime'></td></tr>
|
||||
<tr><th>전투 횟수</th><td id='result_warcnt'></td></tr>
|
||||
<tr><th>전투 페이즈</th><td id='result_phase'></td></tr>
|
||||
<tr><th>준 피해</th><td id='result_killed'></td></tr>
|
||||
<tr><th>받은 피해</th><td id='result_dead'></td></tr>
|
||||
<tr><th>출병자 군량 소모</th><td id='result_attackerRice'></td></tr>
|
||||
<tr><th>수비자 군량 소모</th><td id='result_defenderRice'></td></tr>
|
||||
<tr><th>공격자 스킬</th><td id='result_attackerSkills'></td></tr>
|
||||
<tr class='result_defenderSkills'><th>수비자1 스킬</th><td></td></tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-sm">
|
||||
<div class="card mb-3">
|
||||
<div class="card-header">
|
||||
마지막 전투 로그
|
||||
</div>
|
||||
<div class="card-body" id="generalBattleResultLog">
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-sm">
|
||||
<div class="card mb-3">
|
||||
<div class="card-header">
|
||||
마지막 전투 상세 로그
|
||||
</div>
|
||||
<div class="card-body" id="generalBattleDetailLog">
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,17 @@
|
||||
#container{
|
||||
width:1024px;
|
||||
margin:auto;
|
||||
}
|
||||
|
||||
.defender_add_form .general_detail{
|
||||
display:none;
|
||||
}
|
||||
|
||||
|
||||
.form_sample{
|
||||
display:none;
|
||||
}
|
||||
|
||||
input[type=number]{
|
||||
text-align:right;
|
||||
}
|
||||
+116
-161
@@ -8,43 +8,43 @@ namespace sammo;
|
||||
* Side effect 없이 값의 변환만을 수행하는 함수들의 모음.
|
||||
*/
|
||||
|
||||
|
||||
function NationCharCall($call) {
|
||||
switch($call) {
|
||||
case '명가': $type =13; break;
|
||||
case '음양가': $type =12; break;
|
||||
case '종횡가': $type =11; break;
|
||||
case '불가': $type =10; break;
|
||||
case '도적': $type = 9; break;
|
||||
case '오두미도':$type = 8; break;
|
||||
case '태평도': $type = 7; break;
|
||||
case '도가': $type = 6; break;
|
||||
case '묵가': $type = 5; break;
|
||||
case '덕가': $type = 4; break;
|
||||
case '병가': $type = 3; break;
|
||||
case '유가': $type = 2; break;
|
||||
case '법가': $type = 1; break;
|
||||
default: $type = 0; break;
|
||||
static $invTable = [];
|
||||
if(!$invTable){
|
||||
foreach(getNationTypeList() as $typeID => [$name, $pros, $cons]){
|
||||
$invTable[$name] = $typeID;
|
||||
}
|
||||
}
|
||||
return $type;
|
||||
return $invTable[$call]??0;
|
||||
}
|
||||
|
||||
function getCharacterList(){
|
||||
$infoText = [
|
||||
9=>['안전', '사기 -5, 징·모병 비용 -20%'],
|
||||
8=>['유지', '훈련 -5, 징·모병 비용 -20%'],
|
||||
7=>['재간', '명성 -10%, 징·모병 비용 -20%'],
|
||||
6=>['출세', '명성 +10%, 징·모병 비용 +20%'],
|
||||
5=>['할거', '명성 -10%, 훈련 +5'],
|
||||
4=>['정복', '명성 -10%, 사기 +5'],
|
||||
3=>['패권', '훈련 +5, 징·모병 비용 +20%'],
|
||||
2=>['의협', '사기 +5, 징·모병 비용 +20%'],
|
||||
1=>['대의', '명성 +10%, 훈련 -5'],
|
||||
0=>['왕좌', '명성 +10%, 사기 -5'],
|
||||
10=>['은둔', '명성 -10%, 계급 -10%, 사기 -5, 훈련 -5, 단련 성공률 +10%'],
|
||||
];
|
||||
return $infoText;
|
||||
}
|
||||
|
||||
function CharCall($call) {
|
||||
switch($call) {
|
||||
case '은둔': $type =10; break;
|
||||
case '안전'; $type = 9; break;
|
||||
case '유지'; $type = 8; break;
|
||||
case '재간'; $type = 7; break;
|
||||
case '출세'; $type = 6; break;
|
||||
case '할거'; $type = 5; break;
|
||||
case '정복'; $type = 4; break;
|
||||
case '패권'; $type = 3; break;
|
||||
case '의협'; $type = 2; break;
|
||||
default:
|
||||
case '대의'; $type = 1; break;
|
||||
case '왕좌'; $type = 0; break;
|
||||
static $invTable = [];
|
||||
if(\key_exists($call, $invTable)){
|
||||
return $invTable[$call];
|
||||
}
|
||||
return $type;
|
||||
|
||||
foreach(getCharacterList() as $id => [$name, $info]){
|
||||
$invTable[$name] = $id;
|
||||
}
|
||||
return $invTable[$call];
|
||||
}
|
||||
|
||||
function SpecCall($call) {
|
||||
@@ -120,42 +120,14 @@ function getNationLevel($level) {
|
||||
}
|
||||
|
||||
function getGenChar($type) {
|
||||
switch($type) {
|
||||
case 10: $call = '은둔'; break;
|
||||
case 9: $call = '안전'; break;
|
||||
case 8: $call = '유지'; break;
|
||||
case 7: $call = '재간'; break;
|
||||
case 6: $call = '출세'; break;
|
||||
case 5: $call = '할거'; break;
|
||||
case 4: $call = '정복'; break;
|
||||
case 3: $call = '패권'; break;
|
||||
case 2: $call = '의협'; break;
|
||||
case 1: $call = '대의'; break;
|
||||
case 0: $call = '왕좌'; break;
|
||||
}
|
||||
return $call;
|
||||
return getCharacterList()[$type][0];
|
||||
}
|
||||
|
||||
function getCharInfo(?int $type):?string {
|
||||
if($type === null){
|
||||
return null;
|
||||
}
|
||||
|
||||
$infoText = [
|
||||
10=>['은둔', '명성 -10%, 계급 -10%, 사기 -5, 훈련 -5, 단련 성공률 +10%'],
|
||||
9=>['안전', '사기 -5, 징·모병 비용 -20%'],
|
||||
8=>['유지', '훈련 -5, 징·모병 비용 -20%'],
|
||||
7=>['재간', '명성 -10%, 징·모병 비용 -20%'],
|
||||
6=>['출세', '명성 +10%, 징·모병 비용 +20%'],
|
||||
5=>['할거', '명성 -10%, 훈련 +5'],
|
||||
4=>['정복', '명성 -10%, 사기 +5'],
|
||||
3=>['패권', '훈련 +5, 징·모병 비용 +20%'],
|
||||
2=>['의협', '사기 +5, 징·모병 비용 +20%'],
|
||||
1=>['대의', '명성 +10%, 훈련 -5'],
|
||||
0=>['왕좌', '명성 +10%, 사기 -5'],
|
||||
];
|
||||
|
||||
return $infoText[$type][1]??null;
|
||||
return getCharacterList()[$type][1]??null;
|
||||
}
|
||||
|
||||
function getGenSpecial($type) {
|
||||
@@ -251,24 +223,20 @@ function getSpecialInfo(?int $type):?string{
|
||||
return $infoText[$type][1]??null;
|
||||
}
|
||||
|
||||
function getNationType($type) {
|
||||
switch($type) {
|
||||
case 13: $call = '명 가'; break;
|
||||
case 12: $call = '음 양 가'; break;
|
||||
case 11: $call = '종 횡 가'; break;
|
||||
case 10: $call = '불 가'; break;
|
||||
case 9: $call = '도 적'; break;
|
||||
case 8: $call = '오 두 미 도'; break;
|
||||
case 7: $call = '태 평 도'; break;
|
||||
case 6: $call = '도 가'; break;
|
||||
case 5: $call = '묵 가'; break;
|
||||
case 4: $call = '덕 가'; break;
|
||||
case 3: $call = '병 가'; break;
|
||||
case 2: $call = '유 가'; break;
|
||||
case 1: $call = '법 가'; break;
|
||||
case 0: $call = '-'; break;
|
||||
function getNationType(?int $type) {
|
||||
if($type === null){
|
||||
return '-';
|
||||
}
|
||||
return $call;
|
||||
static $cache = [];
|
||||
if(\key_exists($type, $cache)){
|
||||
return $cache[$type];
|
||||
}
|
||||
|
||||
$text = getNationTypeList()[$type][0]??'-';
|
||||
$text = join(' ', StringUtil::splitString($text));
|
||||
$cache[$type] = $text;
|
||||
|
||||
return $text;
|
||||
}
|
||||
|
||||
|
||||
@@ -287,24 +255,12 @@ function getConnect($con) {
|
||||
return $conname;
|
||||
}
|
||||
|
||||
function getNationType2($type) {
|
||||
switch($type) {
|
||||
case 13: $call = '<font color=cyan>기술↑ 인구↑</font> <font color=magenta>쌀수입↓ 수성↓</font>'; break;
|
||||
case 12: $call = '<font color=cyan>내정↑ 인구↑</font> <font color=magenta>기술↓ 전략↓</font>'; break;
|
||||
case 11: $call = '<font color=cyan>전략↑ 수성↑</font> <font color=magenta>금수입↓ 내정↓</font>'; break;
|
||||
case 10: $call = '<font color=cyan>민심↑ 수성↑</font> <font color=magenta>금수입↓</font>'; break;
|
||||
case 9: $call = '<font color=cyan>계략↑</font> <font color=magenta>금수입↓ 치안↓ 민심↓</font>'; break;
|
||||
case 8: $call = '<font color=cyan>쌀수입↑ 인구↑</font> <font color=magenta>기술↓ 수성↓ 내정↓</font>'; break;
|
||||
case 7: $call = '<font color=cyan>인구↑ 민심↑</font> <font color=magenta>기술↓ 수성↓</font>'; break;
|
||||
case 6: $call = '<font color=cyan>인구↑</font> <font color=magenta>기술↓ 치안↓</font>'; break;
|
||||
case 5: $call = '<font color=cyan>수성↑</font> <font color=magenta>기술↓</font>'; break;
|
||||
case 4: $call = '<font color=cyan>치안↑인구↑ 민심↑</font> <font color=magenta>쌀수입↓ 수성↓</font>'; break;
|
||||
case 3: $call = '<font color=cyan>기술↑ 수성↑</font> <font color=magenta>인구↓ 민심↓</font>'; break;
|
||||
case 2: $call = '<font color=cyan>내정↑ 민심↑</font> <font color=magenta>쌀수입↓</font>'; break;
|
||||
case 1: $call = '<font color=cyan>금수입↑ 치안↑</font> <font color=magenta>인구↓ 민심↓</font>'; break;
|
||||
case 0: $call = '-'; break;
|
||||
function getNationType2(?int $type) {
|
||||
if($type === null){
|
||||
return '-';
|
||||
}
|
||||
return $call;
|
||||
[$name, $pros, $cons] = getNationTypeList()[$type]??['-', '', ''];
|
||||
return "<font color=cyan>{$pros}</font> <font color=magenta>{$cons}</font>";
|
||||
}
|
||||
|
||||
function getLevel($level, $nlevel=8) {
|
||||
@@ -491,74 +447,73 @@ function getTechCall($tech) : string {
|
||||
return "{$techLevel}등급";
|
||||
}
|
||||
|
||||
function getDexCall($dex) : string {
|
||||
if($dex < 2500) { $str = '<font color="navy">F-</font>'; }
|
||||
elseif($dex < 7500) { $str = '<font color="navy">F</font>'; }
|
||||
elseif($dex < 15000) { $str = '<font color="navy">F+</font>'; }
|
||||
elseif($dex < 25000) { $str = '<font color="skyblue">E-</font>'; }
|
||||
elseif($dex < 37500) { $str = '<font color="skyblue">E</font>'; }
|
||||
elseif($dex < 52500) { $str = '<font color="skyblue">E+</font>'; }
|
||||
elseif($dex < 70000) { $str = '<font color="seagreen">D-</font>'; }
|
||||
elseif($dex < 90000) { $str = '<font color="seagreen">D</font>'; }
|
||||
elseif($dex < 112500) { $str = '<font color="seagreen">D+</font>'; }
|
||||
elseif($dex < 137500) { $str = '<font color="teal">C-</font>'; }
|
||||
elseif($dex < 165000) { $str = '<font color="teal">C</font>'; }
|
||||
elseif($dex < 195000) { $str = '<font color="teal">C+</font>'; }
|
||||
elseif($dex < 227500) { $str = '<font color="limegreen">B-</font>'; }
|
||||
elseif($dex < 262500) { $str = '<font color="limegreen">B</font>'; }
|
||||
elseif($dex < 300000) { $str = '<font color="limegreen">B+</font>'; }
|
||||
elseif($dex < 340000) { $str = '<font color="gold">A-</font>'; }
|
||||
elseif($dex < 382500) { $str = '<font color="gold">A</font>'; }
|
||||
elseif($dex < 427500) { $str = '<font color="gold">A+</font>'; }
|
||||
elseif($dex < 475000) { $str = '<font color="darkorange">S-</font>'; }
|
||||
elseif($dex < 525000) { $str = '<font color="darkorange">S</font>'; }
|
||||
elseif($dex < 577500) { $str = '<font color="darkorange">S+</font>'; }
|
||||
elseif($dex < 632500) { $str = '<font color="tomato">SS-</font>'; }
|
||||
elseif($dex < 690000) { $str = '<font color="tomato">SS</font>'; }
|
||||
elseif($dex < 750000) { $str = '<font color="tomato">SS+</font>'; }
|
||||
elseif($dex < 812500) { $str = '<font color="red">SSS-</font>'; }
|
||||
elseif($dex < 877500) { $str = '<font color="red">SSS</font>'; }
|
||||
elseif($dex < 945000) { $str = '<font color="red">SSS+</font>'; }
|
||||
elseif($dex < 1015000) { $str = '<font color="darkviolet">Z-</font>'; }
|
||||
elseif($dex < 1087500) { $str = '<font color="darkviolet">Z</font>'; }
|
||||
elseif($dex < 1162500) { $str = '<font color="darkviolet">Z+</font>'; }
|
||||
else { $str = '<font color="white">?</font>'; }
|
||||
return $str;
|
||||
function getDexLevelList(): array{
|
||||
return [
|
||||
[0, 'navy', 'F-'],
|
||||
[2500, 'navy', 'F'],
|
||||
[7500, 'navy', 'F+'],
|
||||
[15000, 'skyblue', 'E-'],
|
||||
[25000, 'skyblue', 'E'],
|
||||
[37500, 'skyblue', 'E+'],
|
||||
[52500, 'seagreen', 'D-'],
|
||||
[70000, 'seagreen', 'D'],
|
||||
[90000, 'seagreen', 'D+'],
|
||||
[112500, 'teal', 'C-'],
|
||||
[137500, 'teal', 'C'],
|
||||
[165000, 'teal', 'C+'],
|
||||
[195000, 'limegreen', 'B-'],
|
||||
[227500, 'limegreen', 'B'],
|
||||
[262500, 'limegreen', 'B+'],
|
||||
[300000, 'gold', 'A-'],
|
||||
[340000, 'gold', 'A'],
|
||||
[382500, 'gold', 'A+'],
|
||||
[427500, 'darkorange', 'S-'],
|
||||
[475000, 'darkorange', 'S'],
|
||||
[525000, 'darkorange', 'S+'],
|
||||
[577500, 'tomato', 'SS-'],
|
||||
[632500, 'tomato', 'SS'],
|
||||
[690000, 'tomato', 'SS+'],
|
||||
[750000, 'red', 'SSS-'],
|
||||
[812500, 'red', 'SSS'],
|
||||
[877500, 'red', 'SSS+'],
|
||||
[945000, 'darkviolet', 'Z-'],
|
||||
[1015000, 'darkviolet', 'Z'],
|
||||
[1087500, 'darkviolet', 'Z+'],
|
||||
[1162500, 'white', '?']
|
||||
];
|
||||
}
|
||||
|
||||
function getDexLevel($dex) : int {
|
||||
if($dex < 2500) { $lvl = 0; }
|
||||
elseif($dex < 7500) { $lvl = 1; }
|
||||
elseif($dex < 15000) { $lvl = 2; }
|
||||
elseif($dex < 25000) { $lvl = 3; }
|
||||
elseif($dex < 37500) { $lvl = 4; }
|
||||
elseif($dex < 52500) { $lvl = 5; }
|
||||
elseif($dex < 70000) { $lvl = 6; }
|
||||
elseif($dex < 90000) { $lvl = 7; }
|
||||
elseif($dex < 112500) { $lvl = 8; }
|
||||
elseif($dex < 137500) { $lvl = 9; }
|
||||
elseif($dex < 165000) { $lvl = 10; }
|
||||
elseif($dex < 195000) { $lvl = 11; }
|
||||
elseif($dex < 227500) { $lvl = 12; }
|
||||
elseif($dex < 262500) { $lvl = 13; }
|
||||
elseif($dex < 300000) { $lvl = 14; }
|
||||
elseif($dex < 340000) { $lvl = 15; }
|
||||
elseif($dex < 382500) { $lvl = 16; }
|
||||
elseif($dex < 427500) { $lvl = 17; }
|
||||
elseif($dex < 475000) { $lvl = 18; }
|
||||
elseif($dex < 525000) { $lvl = 19; }
|
||||
elseif($dex < 577500) { $lvl = 20; }
|
||||
elseif($dex < 632500) { $lvl = 21; }
|
||||
elseif($dex < 690000) { $lvl = 22; }
|
||||
elseif($dex < 750000) { $lvl = 23; }
|
||||
elseif($dex < 812500) { $lvl = 24; }
|
||||
elseif($dex < 877500) { $lvl = 25; }
|
||||
elseif($dex < 945000) { $lvl = 26; }
|
||||
elseif($dex < 1015000) { $lvl = 27; }
|
||||
elseif($dex < 1087500) { $lvl = 28; }
|
||||
elseif($dex < 1162500) { $lvl = 29; }
|
||||
else { $lvl = 30; }
|
||||
return $lvl;
|
||||
function getDexCall(int $dex) : string {
|
||||
if($dex < 0){
|
||||
throw new \InvalidArgumentException();
|
||||
}
|
||||
|
||||
$color = null;
|
||||
$name = null;
|
||||
foreach(getDexLevelList() as $dexLevel => [$dexKey, $nextColor, $nextName]){
|
||||
if($dex < $dexKey){
|
||||
break;
|
||||
}
|
||||
$color = $nextColor;
|
||||
$name = $nextName;
|
||||
}
|
||||
|
||||
return "<font color='{$color}'>{$name}</font>";
|
||||
}
|
||||
|
||||
function getDexLevel(int $dex) : int {
|
||||
if($dex < 0){
|
||||
throw new \InvalidArgumentException();
|
||||
}
|
||||
|
||||
$retVal = null;
|
||||
foreach(getDexLevelList() as $dexLevel => [$dexKey, $nextColor, $nextName]){
|
||||
if($dex < $dexKey){
|
||||
break;
|
||||
}
|
||||
$retVal = $dexLevel;
|
||||
}
|
||||
return $dexLevel;
|
||||
}
|
||||
|
||||
function getDexLog($dex1, $dex2) {
|
||||
|
||||
@@ -5,6 +5,51 @@ namespace sammo;
|
||||
* 게임 룰에 해당하는 함수 모음
|
||||
*/
|
||||
|
||||
function getNationLevelList():array{
|
||||
$table = [
|
||||
0 => ['방랑군', 2, 0],
|
||||
1 => ['호족', 2, 1],
|
||||
2 => ['군벌', 4, 2],
|
||||
3 => ['주자사', 4, 5],
|
||||
4 => ['주목', 6, 8],
|
||||
5 => ['공', 6, 11],
|
||||
6 => ['왕', 8, 16],
|
||||
7 => ['황제', 8, 21],
|
||||
];
|
||||
return $table;
|
||||
}
|
||||
|
||||
function getNationTypeList():array{
|
||||
$table = [
|
||||
13=>['명가', '기술↑ 인구↑', '쌀수입↓ 수성↓'],
|
||||
12=>['음양가', '내정↑ 인구↑', '기술↓ 전략↓'],
|
||||
11=>['종횡가', '전략↑ 수성↑', '금수입↓ 내정↓'],
|
||||
10=>['불가', '민심↑ 수성↑', '금수입↓'],
|
||||
9=>['도적', '계략↑', '금수입↓ 치안↓ 민심↓'],
|
||||
8=>['오두미도', '쌀수입↑ 인구↑', '기술↓ 수성↓ 내정↓'],
|
||||
7=>['태평도', '인구↑ 민심↑', '기술↓ 수성↓'],
|
||||
6=>['도가', '인구↑', '기술↓ 치안↓'],
|
||||
5=>['묵가', '수성↑', '기술↓'],
|
||||
4=>['덕가', '치안↑인구↑ 민심↑', '쌀수입↓ 수성↓'],
|
||||
3=>['병가', '기술↑ 수성↑', '인구↓ 민심↓'],
|
||||
2=>['유가', '내정↑ 민심↑', '쌀수입↓'],
|
||||
1=>['법가', '금수입↑ 치안↑', '인구↓ 민심↓'],
|
||||
];
|
||||
return $table;
|
||||
}
|
||||
|
||||
function getCityLevelList():array{
|
||||
return [
|
||||
1 => '수',
|
||||
2 => '진',
|
||||
3 => '관',
|
||||
4 => '이',
|
||||
5 => '소',
|
||||
6 => '중',
|
||||
7 => '대',
|
||||
8 => '특'
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* 게임 내부에 사용하는 유틸리티 함수들을 분리
|
||||
|
||||
@@ -608,7 +608,6 @@ function process_35(&$general) {
|
||||
$destNation = getNationStaticInfo($destNationID);
|
||||
|
||||
$generalList = $db->query('SELECT `no`,leader,horse,power,weap,intel,book,injury,level,special,special2 FROM general WHERE city=%i and nation=%i', $destCity['city'], $destCity['nation']);
|
||||
|
||||
[
|
||||
$srcGenScore,
|
||||
$srcSpecialScore,
|
||||
|
||||
@@ -0,0 +1,417 @@
|
||||
<?php
|
||||
namespace sammo;
|
||||
|
||||
include "lib.php";
|
||||
include "func.php";
|
||||
|
||||
$session = Session::requireLogin([])->setReadOnly();
|
||||
$userID = Session::getUserID();
|
||||
|
||||
$query = Util::getReq('query');
|
||||
if($query === null){
|
||||
Json::die([
|
||||
'result'=>false,
|
||||
'reason'=>'입력값이 없습니다.'
|
||||
]);
|
||||
}
|
||||
|
||||
$action = Util::getReq('action');
|
||||
if($action === null || !in_array($action, ['reorder', 'battle'])){
|
||||
Json::die([
|
||||
'result'=>false,
|
||||
'reason'=>'원하는 동작이 지정되지 않았습니다.'
|
||||
]);
|
||||
}
|
||||
|
||||
$query = Json::decode($query);
|
||||
if($query === null){
|
||||
Json::die([
|
||||
'result'=>false,
|
||||
'reason'=>'올바르지 않은 JSON입니다.'
|
||||
]);
|
||||
}
|
||||
|
||||
|
||||
$defaultCheck = [
|
||||
'required'=>[
|
||||
'attackerGeneral', 'attackerCity', 'attackerNation',
|
||||
'defenderGenerals', 'defenderCity', 'defenderNation',
|
||||
'year', 'month', 'repeatCnt'
|
||||
],
|
||||
'integer'=>[
|
||||
'year','month','repeatCnt'
|
||||
],
|
||||
'between'=>[
|
||||
['month', [1, 12]]
|
||||
],
|
||||
'in'=>[
|
||||
['repeatCnt', [1, 1000]]
|
||||
],
|
||||
'min'=>[
|
||||
['year', 0]
|
||||
],
|
||||
'array'=>[
|
||||
'attackerGeneral', 'attackerCity', 'attackerNation',
|
||||
'defenderGenerals', 'defenderCity', 'defenderNation'
|
||||
],
|
||||
];
|
||||
|
||||
$v = new Validator($query);
|
||||
$v->rules($defaultCheck);
|
||||
if(!$v->validate()){
|
||||
Json::die([
|
||||
'result'=>false,
|
||||
'reason'=>$v->errorStr()
|
||||
]);
|
||||
}
|
||||
|
||||
$year = $query['year'];
|
||||
$month = $query['month'];
|
||||
$repeatCnt = $query['repeatCnt'];
|
||||
|
||||
$rawAttacker = $query['attackerGeneral'];
|
||||
$rawAttacker['turntime'] = date('Y-m-d H:i:s');
|
||||
$rawAttackerCity = $query['attackerCity'];
|
||||
$rawAttackerNation = $query['attackerNation'];
|
||||
|
||||
$defenderList = $query['defenderGenerals'];
|
||||
$rawDefenderCity = $query['defenderCity'];
|
||||
$rawDefenderNation = $query['defenderNation'];
|
||||
|
||||
|
||||
$generalCheck = [
|
||||
'required'=>[
|
||||
'no', 'name', 'nation', 'turntime', 'personal', 'special2', 'crew', 'crewtype', 'atmos', 'train',
|
||||
'intel', 'intel2', 'book', 'power', 'power2', 'weap', 'injury', 'leader', 'leader2', 'horse', 'item',
|
||||
'explevel', 'experience', 'dedication', 'level', 'gold', 'rice', 'dex0', 'dex10', 'dex20', 'dex30', 'dex40',
|
||||
'warnum', 'killnum', 'deathnum', 'killcrew', 'deathcrew', 'recwar'
|
||||
],
|
||||
'integer'=>[
|
||||
'no', 'nation', 'personal', 'special2', 'crew', 'crewtype', 'atmos', 'train',
|
||||
'intel', 'intel2', 'book', 'power', 'power2', 'weap', 'injury', 'leader', 'leader2', 'horse', 'item',
|
||||
'explevel', 'experience', 'dedication', 'level', 'gold', 'rice', 'dex0', 'dex10', 'dex20', 'dex30', 'dex40',
|
||||
'warnum', 'killnum', 'deathnum', 'killcrew', 'deathcrew'
|
||||
],
|
||||
'min'=>[
|
||||
['no', 1],
|
||||
['nation', 1],
|
||||
['crew', 0],
|
||||
['intel', 0],
|
||||
['power', 0],
|
||||
['leader', 0],
|
||||
['experience', 0],
|
||||
['gold', 0],
|
||||
['rice', 0],
|
||||
['dex0', 0],
|
||||
['dex10', 0],
|
||||
['dex20', 0],
|
||||
['dex30', 0],
|
||||
['dex40', 0],
|
||||
],
|
||||
'between'=>[
|
||||
['train', [40, GameConst::$maxTrainByWar]],
|
||||
['atmos', [40, GameConst::$maxAtmosByWar]],
|
||||
['book', [0, 26]],
|
||||
['weap', [0, 26]],
|
||||
['horse', [0, 26]],
|
||||
['item', [0, 26]],
|
||||
['explevel', [0, 300]],
|
||||
['injury', [0, 80]],
|
||||
['level', [1, 12]]
|
||||
],
|
||||
'in'=>[
|
||||
['personal', array_keys(getCharacterList())],
|
||||
['special2', array_merge(array_keys(SpecialityConst::WAR), [0])],
|
||||
['crewtype', array_keys(GameUnitConst::all())],
|
||||
]
|
||||
];
|
||||
|
||||
$v = new Validator($rawAttacker);
|
||||
$v->rules($generalCheck);
|
||||
if(!$v->validate()){
|
||||
Json::die([
|
||||
'result'=>false,
|
||||
'reason'=>'[출병자]'.$v->errorStr()
|
||||
]);
|
||||
}
|
||||
|
||||
foreach($defenderList as $idx=>$rawDefenderGeneral){
|
||||
$v = new Validator($rawDefenderGeneral);
|
||||
$v->rules($generalCheck);
|
||||
if(!$v->validate()){
|
||||
$idx+=1;
|
||||
Json::die([
|
||||
'result'=>false,
|
||||
'reason'=>"[수비자{$idx}]".$v->errorStr()
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
$cityCheck = [
|
||||
'required'=>[
|
||||
'city', 'nation', 'supply', 'name',
|
||||
'pop', 'agri', 'comm', 'secu', 'def', 'wall',
|
||||
'rate', 'level',
|
||||
'pop2', 'agri2', 'comm2', 'secu2', 'def2', 'wall2',
|
||||
'dead', 'state', 'gen1', 'gen2', 'gen3', 'conflict',
|
||||
],
|
||||
'numeric'=>[
|
||||
'pop', 'agri', 'comm', 'secu', 'def', 'wall', 'rate', 'dead'
|
||||
],
|
||||
'integer'=>[
|
||||
'city', 'nation', 'supply',
|
||||
'pop2', 'agri2', 'comm2', 'secu2', 'def2', 'wall2',
|
||||
'state', 'gen1', 'gen2', 'gen3'
|
||||
],
|
||||
'min'=>[
|
||||
['def', 0],
|
||||
['wall', 0],
|
||||
['rate', 0],
|
||||
['pop', 0],
|
||||
['comm', 0],
|
||||
['secu', 0],
|
||||
['city', 1],
|
||||
['nation', 0]
|
||||
],
|
||||
'in'=>[
|
||||
['level', array_keys(getCityLevelList())]
|
||||
]
|
||||
];
|
||||
|
||||
$v = new Validator($rawAttackerCity);
|
||||
$v->rules($cityCheck);
|
||||
if(!$v->validate()){
|
||||
Json::die([
|
||||
'result'=>false,
|
||||
'reason'=>'[출병도시]'.$v->errorStr()
|
||||
]);
|
||||
}
|
||||
|
||||
$v = new Validator($rawDefenderCity);
|
||||
$v->rules($cityCheck);
|
||||
if(!$v->validate()){
|
||||
Json::die([
|
||||
'result'=>false,
|
||||
'reason'=>'[수비도시]'.$v->errorStr()
|
||||
]);
|
||||
}
|
||||
|
||||
$nationCheck = [
|
||||
'required'=>[
|
||||
'type', 'tech', 'level', 'capital',
|
||||
'nation', 'name', 'gold', 'rice', 'totaltech', 'gennum'
|
||||
],
|
||||
'integer'=>[
|
||||
'type', 'level', 'capital', 'nation', 'gennum',
|
||||
],
|
||||
'numeric'=>[
|
||||
'tech', 'gold', 'rice', 'totaltech'
|
||||
],
|
||||
'min'=>[
|
||||
['tech', 0],
|
||||
['totaltech', 0],
|
||||
['gold', 0],
|
||||
['rice', 0],
|
||||
['gennum', 1],
|
||||
['gen1', 0],
|
||||
['gen2', 0],
|
||||
['gen3', 0],
|
||||
],
|
||||
'in'=>[
|
||||
['type', array_keys(getNationTypeList())],
|
||||
['level', array_keys(getNationLevelList())]
|
||||
]
|
||||
];
|
||||
|
||||
$v = new Validator($rawAttackerNation);
|
||||
$v->rules($nationCheck);
|
||||
if(!$v->validate()){
|
||||
Json::die([
|
||||
'result'=>false,
|
||||
'reason'=>'[출병국]'.$v->errorStr()
|
||||
]);
|
||||
}
|
||||
|
||||
$v = new Validator($rawDefenderNation);
|
||||
$v->rules($nationCheck);
|
||||
if(!$v->validate()){
|
||||
Json::die([
|
||||
'result'=>false,
|
||||
'reason'=>'[수비국]'.$v->errorStr()
|
||||
]);
|
||||
}
|
||||
|
||||
if($action == 'reorder'){
|
||||
usort($defenderList, function($lhs, $rhs){
|
||||
return -(extractBattleOrder($lhs) <=> extractBattleOrder($rhs));
|
||||
});
|
||||
|
||||
$order = [];
|
||||
foreach($defenderList as $rawDefenderGeneral){
|
||||
$order[] = $rawDefenderGeneral['no'];
|
||||
}
|
||||
|
||||
Json::die([
|
||||
'result'=>true,
|
||||
'reason'=>'success',
|
||||
'order'=>$order
|
||||
]);
|
||||
}
|
||||
|
||||
usort($defenderList, function($lhs, $rhs){
|
||||
return -(extractBattleOrder($lhs) <=> extractBattleOrder($rhs));
|
||||
});
|
||||
|
||||
$db = DB::db();
|
||||
$gameStor = KVStorage::getStorage($db, 'game_env');
|
||||
$startYear = $gameStor->startyear;
|
||||
$cityRate = Util::round(($year - $startYear) / 1.5) + 60;
|
||||
|
||||
|
||||
function simulateBattle(
|
||||
$rawAttacker, $rawAttackerCity, $rawAttackerNation,
|
||||
$defenderList, $rawDefenderCity, $rawDefenderNation,
|
||||
$startYear, $year, $month, $cityRate
|
||||
){
|
||||
$attacker = new WarUnitGeneral($rawAttacker, $rawAttackerCity, $rawAttackerNation, true, $year, $month);
|
||||
$city = new WarUnitCity($rawDefenderCity, $rawDefenderNation, $year, $month, $cityRate);
|
||||
|
||||
$iterDefender = new \ArrayIterator($defenderList);
|
||||
$iterDefender->rewind();
|
||||
|
||||
$battleResult = [];
|
||||
|
||||
$attackerRice = $rawAttacker['rice'];
|
||||
$defenderRice = 0;
|
||||
|
||||
$getNextDefender = function(?WarUnit $prevDefender, bool $reqNext)
|
||||
use ($iterDefender, $rawDefenderCity, $rawDefenderNation, $year, $month, &$battleResult, &$defenderRice) {
|
||||
if($prevDefender !== null){
|
||||
$prevDefender->getLogger()->rollback();
|
||||
$battleResult[] = $prevDefender;
|
||||
if($prevDefender instanceof WarUnitGeneral){
|
||||
$defenderRice -= $prevDefender->getVar('rice');
|
||||
}
|
||||
}
|
||||
|
||||
if(!$reqNext){
|
||||
return null;
|
||||
}
|
||||
|
||||
if(!$iterDefender->valid()){
|
||||
return null;
|
||||
}
|
||||
|
||||
$rawGeneral = $iterDefender->current();
|
||||
if(extractBattleOrder($rawGeneral) <= 0){
|
||||
return null;
|
||||
}
|
||||
|
||||
$defenderRice += $rawGeneral['rice'];
|
||||
|
||||
$retVal = new WarUnitGeneral($rawGeneral, $rawDefenderCity, $rawDefenderNation, false, $year, $month);
|
||||
$iterDefender->next();
|
||||
return $retVal;
|
||||
};
|
||||
|
||||
$conquerCity = processWar_NG($attacker, $getNextDefender, $city, $year - $startYear);
|
||||
|
||||
$rawDefenderCity = $city->getRaw();
|
||||
$updateAttackerNation = [];
|
||||
$updateDefenderNation = [];
|
||||
|
||||
$attackerRice -= $attacker->getVar('rice');
|
||||
|
||||
if($city->getPhase() > 0){
|
||||
$rice = $city->getKilled() / 100 * 0.8;
|
||||
$rice *= $city->getCrewType()->rice;
|
||||
$rice *= getTechCost($rawDefenderNation['tech']);
|
||||
$rice *= $cityRate / 100 - 0.2;
|
||||
Util::setRound($rice);
|
||||
|
||||
$defenderRice += $rice;
|
||||
}
|
||||
|
||||
$totalDead = $attacker->getKilled() + $attacker->getDead();
|
||||
$attackerCityDead = $totalDead * 0.4;
|
||||
$defenderCityDead = $totalDead * 0.6;
|
||||
|
||||
return [$attacker, $city, $battleResult, $conquerCity, $attackerRice, $defenderRice];
|
||||
}
|
||||
|
||||
$lastWarLog = [];
|
||||
|
||||
$attackerKilled = 0;
|
||||
$attackerDead = 0;
|
||||
|
||||
$attackerAvgRice = 0;
|
||||
$defenderAvgRice = 0;
|
||||
|
||||
$avgPhase = 0;
|
||||
$avgWar = 0;
|
||||
|
||||
$attackerActivatedSkills = [];
|
||||
$defendersActivatedSkills = [];
|
||||
|
||||
foreach(range(1, $repeatCnt) as $repeatIdx){
|
||||
[$attacker, $city, $battleResult, $conquerCity, $attackerRice, $defenderRice] = simulateBattle(
|
||||
$rawAttacker, $rawAttackerCity, $rawAttackerNation,
|
||||
$defenderList, $rawDefenderCity, $rawDefenderNation,
|
||||
$startYear, $year, $month, $cityRate
|
||||
);
|
||||
$lastWarLog = Util::mapWithKey(function($key, $values){
|
||||
return ConvertLog(join('<br>', $values));
|
||||
}, $attacker->getLogger()->rollback());
|
||||
|
||||
$avgPhase += $attacker->getPhase() / $repeatCnt;
|
||||
|
||||
$attackerKilled += $attacker->getKilled() / $repeatCnt;
|
||||
$attackerDead += $attacker->getDead() / $repeatCnt;
|
||||
|
||||
$attackerAvgRice += $attackerRice / $repeatCnt;
|
||||
$defenderAvgRice += $defenderRice / $repeatCnt;
|
||||
|
||||
$avgWar += count($battleResult) / $repeatCnt;
|
||||
|
||||
foreach($attacker->getActivatedSkillLog() as $skillName => $skillCnt){
|
||||
if(!key_exists($skillName, $attackerActivatedSkills)){
|
||||
$attackerActivatedSkills[$skillName] = $skillCnt / $repeatCnt;
|
||||
}
|
||||
else{
|
||||
$attackerActivatedSkills[$skillName] += $skillCnt / $repeatCnt;
|
||||
}
|
||||
}
|
||||
|
||||
foreach($battleResult as $idx=>$defender){
|
||||
while($idx >= count($defendersActivatedSkills)){
|
||||
$defendersActivatedSkills[] = [];
|
||||
}
|
||||
|
||||
$activatedSkills = &$defendersActivatedSkills[$idx];
|
||||
foreach($defender->getActivatedSkillLog() as $skillName => $skillCnt){
|
||||
if(!key_exists($skillName, $activatedSkills)){
|
||||
$activatedSkills[$skillName] = $skillCnt / $repeatCnt;
|
||||
}
|
||||
else{
|
||||
$activatedSkills[$skillName] += $skillCnt / $repeatCnt;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
Json::die([
|
||||
'result'=>true,
|
||||
'datetime'=>$rawAttacker['turntime'],
|
||||
'reason'=>'success',
|
||||
'lastWarLog'=>$lastWarLog,
|
||||
'avgWar'=>$avgWar,
|
||||
'phase'=>$avgPhase,
|
||||
'killed'=>$attackerKilled,
|
||||
'dead'=>$attackerDead,
|
||||
'attackerRice'=>$attackerAvgRice,
|
||||
'defenderRice'=>$defenderAvgRice,
|
||||
'attackerSkills'=>$attackerActivatedSkills,
|
||||
'defendersSkills'=>$defendersActivatedSkills,
|
||||
]);
|
||||
@@ -0,0 +1,800 @@
|
||||
jQuery(function($){
|
||||
|
||||
|
||||
var $generalForm = $('.form_sample .general_detail');
|
||||
var $defenderHeaderForm = $('.form_sample .card-header');
|
||||
var $defenderColumn = $('.defender-column');
|
||||
|
||||
var defenderNoList = {};
|
||||
|
||||
var $attackerCard = $('.attacker_form');
|
||||
|
||||
var initBasicEvent = function(){
|
||||
|
||||
$('.form_injury').change(function(){
|
||||
var $this = $(this);
|
||||
var $general = getGeneralDetail($this);
|
||||
var $helptext = $general.find('.injury_helptext');
|
||||
|
||||
var injury = parseInt($this.val());
|
||||
//FIXME: PHP 코드와 항상 일치하도록 변경
|
||||
var text = '건강';
|
||||
var color = 'white';
|
||||
if(injury > 60){
|
||||
text = '위독';
|
||||
color = 'red';
|
||||
}
|
||||
else if(injury > 40){
|
||||
text = '심각';
|
||||
color = 'magenta';
|
||||
}
|
||||
else if(injury > 20){
|
||||
text = '중상';
|
||||
color = 'orange';
|
||||
}
|
||||
else if(injury > 0){
|
||||
text = '경상';
|
||||
color = 'yellow';
|
||||
}
|
||||
$helptext.html(text).css('color', color);
|
||||
});
|
||||
|
||||
$('.export_general').click(function(){
|
||||
var $btn = $(this);
|
||||
var $general = getGeneralDetail($btn);
|
||||
|
||||
var values = exportGeneralInfo($general);
|
||||
console.log(values);
|
||||
});
|
||||
$('.delete-defender').click(function(){
|
||||
var $card = getGeneralFrame($(this));
|
||||
deleteDefender($card);
|
||||
});
|
||||
$('.copy-defender').click(function(){
|
||||
var $card = getGeneralFrame($(this));
|
||||
copyDefender($card);
|
||||
});
|
||||
|
||||
$('.add-defender').click(function(){
|
||||
addDefender();
|
||||
});
|
||||
|
||||
$('.btn-general-load').click(function(){
|
||||
var $file = $(this).prev();
|
||||
$file[0].click();
|
||||
})
|
||||
|
||||
$('.form_load_general_file').on('change', function(e){
|
||||
e.preventDefault();
|
||||
var $this = $(this);
|
||||
var $card = getGeneralFrame($this);
|
||||
|
||||
var files = e.target.files;
|
||||
|
||||
importGeneralInfoByFile(files, $card);
|
||||
return false;
|
||||
});
|
||||
|
||||
$('.btn-general-save').click(function(){
|
||||
var $this = $(this);
|
||||
var $general = getGeneralDetail($this);
|
||||
var generalData = exportGeneralInfo($general);
|
||||
|
||||
var filename = "general_{0}.json".format(generalData.name);
|
||||
var saveData = JSON.stringify({
|
||||
objType:'general',
|
||||
data:generalData
|
||||
}, null, 4);
|
||||
|
||||
download(saveData, filename, 'application/json');
|
||||
});
|
||||
|
||||
$('.btn-battle-load').click(function(){
|
||||
var $file = $(this).prev();
|
||||
$file[0].click();
|
||||
})
|
||||
|
||||
$('.form_load_battle_file').on('change', function(e){
|
||||
e.preventDefault();
|
||||
var $this = $(this);
|
||||
var files = e.target.files;
|
||||
|
||||
importBattleInfoByFile(files);
|
||||
return false;
|
||||
});
|
||||
|
||||
$('.btn-battle-save').click(function(){
|
||||
var battleData = exportAllData();
|
||||
var filename = "battle_{0}.json".format(moment().format('YYYYMMDD_hhmmss'));
|
||||
var saveData = JSON.stringify({
|
||||
objType:'battle',
|
||||
data:battleData
|
||||
}, null, 4);
|
||||
|
||||
download(saveData, filename, 'application/json');
|
||||
})
|
||||
|
||||
var $generals = $('.general_detail');
|
||||
$generals.bind('dragover dragleave', function(e) {
|
||||
e.stopPropagation()
|
||||
e.preventDefault()
|
||||
})
|
||||
$generals.bind('drop', function(e){
|
||||
e.preventDefault();
|
||||
var $this = $(this);
|
||||
var $card = getGeneralFrame($this);
|
||||
|
||||
var files = e.originalEvent.dataTransfer.files;
|
||||
|
||||
importGeneralInfoByFile(files, $card);
|
||||
return false;
|
||||
});
|
||||
|
||||
var $battlePad = $('.dragpad_battle');
|
||||
$battlePad.bind('dragover dragleave', function(e) {
|
||||
e.stopPropagation()
|
||||
e.preventDefault()
|
||||
})
|
||||
$battlePad.bind('drop', function(e){
|
||||
e.preventDefault();
|
||||
|
||||
var files = e.originalEvent.dataTransfer.files;
|
||||
|
||||
importBattleInfoByFile(files);
|
||||
return false;
|
||||
});
|
||||
}
|
||||
|
||||
var importGeneralInfo = function($general, data){
|
||||
var setVal = function(query, val){
|
||||
$general.find(query).val(val).change();
|
||||
}
|
||||
|
||||
setVal('.form_general_name', data.name);
|
||||
|
||||
setVal('.form_general_level', data.level);
|
||||
setVal('.form_exp_level', data.explevel);
|
||||
setVal('.form_injury', data.injury);
|
||||
|
||||
setVal('.form_leadership', data.leader);
|
||||
setVal('.form_general_horse', data.horse);
|
||||
setVal('.form_power', data.power);
|
||||
setVal('.form_general_weap', data.weap);
|
||||
setVal('.form_intel', data.intel);
|
||||
setVal('.form_general_book', data.book);
|
||||
setVal('.form_general_item', data.item);
|
||||
|
||||
setVal('.form_injury', data.injury);
|
||||
|
||||
setVal('.form_rice', data.rice);
|
||||
|
||||
setVal('.form_general_character', data.personal);
|
||||
setVal('.form_general_special_war', data.special2);
|
||||
|
||||
setVal('.form_crew', data.crew);
|
||||
setVal('.form_crewtype', data.crewtype);
|
||||
setVal('.form_atmos', data.atmos);
|
||||
setVal('.form_train', data.train);
|
||||
|
||||
setVal('.form_dex0', data.dex0);
|
||||
setVal('.form_dex10', data.dex10);
|
||||
setVal('.form_dex20', data.dex20);
|
||||
setVal('.form_dex30', data.dex30);
|
||||
setVal('.form_dex40', data.dex40);
|
||||
setVal('.form_defend_mode', data.mode);
|
||||
|
||||
if(!setGeneralNo($general, data.no)){
|
||||
setGeneralNo($general, generateNewGeneralNo());
|
||||
}
|
||||
}
|
||||
|
||||
var exportGeneralInfo = function($general){
|
||||
var getInt = function(query){
|
||||
return parseInt($general.find(query).val());
|
||||
}
|
||||
|
||||
var getVal = function(query){
|
||||
return $general.find(query).val();
|
||||
}
|
||||
|
||||
return {
|
||||
no:getGeneralNo($general),
|
||||
name:getVal('.form_general_name'),
|
||||
level:getInt('.form_general_level'),
|
||||
explevel:getInt('.form_exp_level'),
|
||||
|
||||
leader:getInt('.form_leadership'),
|
||||
horse:getInt('.form_general_horse'),
|
||||
power:getInt('.form_power'),
|
||||
weap:getInt('.form_general_weap'),
|
||||
intel:getInt('.form_intel'),
|
||||
book:getInt('.form_general_book'),
|
||||
item:getInt('.form_general_item'),
|
||||
|
||||
injury:getInt('.form_injury'),
|
||||
|
||||
rice:getInt('.form_rice'),
|
||||
|
||||
personal:getInt('.form_general_character'),
|
||||
special2:getInt('.form_general_special_war'),
|
||||
|
||||
crew:getInt('.form_crew'),
|
||||
crewtype:getInt('.form_crewtype'),
|
||||
atmos:getInt('.form_atmos'),
|
||||
train:getInt('.form_train'),
|
||||
|
||||
dex0:getInt('.form_dex0'),
|
||||
dex10:getInt('.form_dex10'),
|
||||
dex20:getInt('.form_dex20'),
|
||||
dex30:getInt('.form_dex30'),
|
||||
dex40:getInt('.form_dex40'),
|
||||
mode:getInt('.form_defend_mode'),
|
||||
};
|
||||
}
|
||||
|
||||
var importBattleInfoByFile = function(files){
|
||||
if(files === null){
|
||||
alert('파일 에러!');
|
||||
return false;
|
||||
}
|
||||
|
||||
if(files.length < 1){
|
||||
alert("파일 에러!");
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
var file = files[0];
|
||||
if(file.size > 1024*1024){
|
||||
alert('파일이 너무 큽니다!');
|
||||
return false;
|
||||
}
|
||||
if(file.type === ''){
|
||||
alert('폴더를 업로드할 수 없습니다!');
|
||||
return false;
|
||||
}
|
||||
|
||||
var reader = new FileReader();
|
||||
reader.onload = function(){
|
||||
var battleData = {};
|
||||
try {
|
||||
battleData = JSON.parse(reader.result);
|
||||
} catch(e) {
|
||||
alert('올바르지 않은 파일 형식입니다');
|
||||
return false;
|
||||
}
|
||||
|
||||
if(!('objType' in battleData)){
|
||||
alert('파일 형식을 확인할 수 없습니다');
|
||||
return false;
|
||||
}
|
||||
|
||||
if(battleData.objType != 'battle'){
|
||||
alert('전투 데이터가 아닙니다');
|
||||
return false;
|
||||
}
|
||||
|
||||
importBattleInfo(battleData.data);
|
||||
return true;
|
||||
};
|
||||
|
||||
try {
|
||||
|
||||
reader.readAsText(file);
|
||||
}
|
||||
catch(e) {
|
||||
alert('파일을 읽는데 실패했습니다.');
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
var importGeneralInfoByFile = function(files, $card){
|
||||
if($card === undefined){
|
||||
$card = addDefender();
|
||||
}
|
||||
|
||||
if(files === null){
|
||||
alert('파일 에러!');
|
||||
return false;
|
||||
}
|
||||
|
||||
if(files.length < 1){
|
||||
alert("파일 에러!");
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
var file = files[0];
|
||||
if(file.size > 1024*1024){
|
||||
alert('파일이 너무 큽니다!');
|
||||
return false;
|
||||
}
|
||||
if(file.type === ''){
|
||||
alert('폴더를 업로드할 수 없습니다!');
|
||||
return false;
|
||||
}
|
||||
|
||||
var reader = new FileReader();
|
||||
reader.onload = function(){
|
||||
var generalData = {};
|
||||
try {
|
||||
generalData = JSON.parse(reader.result);
|
||||
} catch(e) {
|
||||
alert('올바르지 않은 파일 형식입니다');
|
||||
return false;
|
||||
}
|
||||
|
||||
if(!('objType' in generalData)){
|
||||
alert('파일 형식을 확인할 수 없습니다');
|
||||
return false;
|
||||
}
|
||||
|
||||
if(generalData.objType == 'battle'){
|
||||
importBattleInfo(generalData.data);
|
||||
return true;
|
||||
}
|
||||
if(generalData.objType != 'general'){
|
||||
alert('장수 데이터가 아닙니다');
|
||||
return false;
|
||||
}
|
||||
|
||||
$card.find('.form_load_general_file').val('');
|
||||
|
||||
importGeneralInfo($card, generalData.data);
|
||||
return true;
|
||||
};
|
||||
|
||||
try {
|
||||
|
||||
reader.readAsText(file);
|
||||
}
|
||||
catch(e) {
|
||||
alert('파일을 읽는데 실패했습니다.');
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
var extendGeneralInfoForDB = function(generalData){
|
||||
|
||||
var dbVal = {
|
||||
nation: (generalData.no)<=1 ? 1 : 2,
|
||||
city: (generalData.no)<=1 ? 1 : 3,
|
||||
turntime:'2018-08-26 12:00',
|
||||
special:0,
|
||||
leader2:0,
|
||||
power2:0,
|
||||
intel2:0,
|
||||
|
||||
gold:10000,
|
||||
|
||||
dedication:0,
|
||||
warnum:0,
|
||||
killnum:0,
|
||||
deathnum:0,
|
||||
|
||||
killcrew:20000,
|
||||
deathcrew:20000,
|
||||
recwar:'SUCCESS',
|
||||
experience:Math.pow(generalData.explevel, 2),
|
||||
};
|
||||
|
||||
return $.extend({}, generalData, dbVal);
|
||||
}
|
||||
|
||||
var getGeneralFrame = function($btn){
|
||||
var $card = $btn.closest('.general_form');
|
||||
return $card;
|
||||
}
|
||||
|
||||
var getGeneralDetail = function($btn){
|
||||
var $card = getGeneralFrame($btn);
|
||||
var $general = $card.find('.general_detail');
|
||||
return $general;
|
||||
}
|
||||
|
||||
var getGeneralNo = function($btn){
|
||||
return parseInt(getGeneralFrame($btn).data('general_no'));
|
||||
}
|
||||
|
||||
var setGeneralNo = function($btn, value){
|
||||
if(value == 1){
|
||||
//1번은 무조건 공격자임
|
||||
return false;
|
||||
}
|
||||
if(value in defenderNoList){
|
||||
return false;
|
||||
}
|
||||
var $card = getGeneralFrame($btn);
|
||||
$card.data('general_no', value);
|
||||
defenderNoList[value] = $card;
|
||||
return true;
|
||||
}
|
||||
|
||||
var generateNewGeneralNo = function(){
|
||||
while(true){
|
||||
var newGeneralNo = parseInt(Math.random()*(1<<24))+2;
|
||||
if(newGeneralNo in defenderNoList){
|
||||
continue;
|
||||
}
|
||||
return newGeneralNo;
|
||||
}
|
||||
}
|
||||
|
||||
var deleteGeneralNo = function($btn){
|
||||
var $card = getGeneralFrame($btn);
|
||||
$card.removeData('general_no');
|
||||
var generalNo = getGeneralNo($card);
|
||||
delete defenderNoList[generalNo];
|
||||
}
|
||||
|
||||
var addDefender = function($cardAfter){
|
||||
var $newCard = $('<div class="card mb-2 defender_form general_form"></div>');
|
||||
|
||||
if($cardAfter === undefined){
|
||||
$defenderColumn.append($newCard);
|
||||
}
|
||||
else{
|
||||
$cardAfter.after($newCard);
|
||||
}
|
||||
|
||||
$newCard.append($defenderHeaderForm.clone(true,true));
|
||||
$newCard.append($generalForm.clone(true,true));
|
||||
|
||||
$newGeneral = getGeneralDetail($newCard);
|
||||
setGeneralNo($newCard, generateNewGeneralNo());
|
||||
|
||||
return $newCard;
|
||||
}
|
||||
|
||||
var deleteDefender = function($card){
|
||||
deleteGeneralNo($card);
|
||||
$card.detach();
|
||||
}
|
||||
|
||||
var copyDefender = function($card){
|
||||
var $general = getGeneralDetail($card);
|
||||
|
||||
var generalData = exportGeneralInfo($general);
|
||||
var $newObj = addDefender($card);
|
||||
importGeneralInfo(getGeneralDetail($newObj), generalData);
|
||||
}
|
||||
|
||||
var importBattleInfo = function(battleData){
|
||||
|
||||
$('.form_load_battle_file').val('');
|
||||
console.log(battleData);
|
||||
|
||||
var $attackerNation = $('.attacker_nation');
|
||||
var $defenderNation = $('.defender_nation');
|
||||
|
||||
var attackerGeneral = battleData.attackerGeneral;
|
||||
var attackerCity = battleData.attackerCity;
|
||||
var attackerNation = battleData.attackerNation;
|
||||
|
||||
var defenderGenerals = battleData.defenderGenerals;
|
||||
var defenderCity = battleData.defenderCity;
|
||||
var defenderNation = battleData.defenderNation;
|
||||
|
||||
$('#year').val(battleData.year);
|
||||
$('#month').val(battleData.month);
|
||||
$('#repeat_cnt').val(battleData.repeatCnt);
|
||||
|
||||
$('.delete-defender').click();
|
||||
|
||||
$attackerNation.find('.form_nation_type').val(attackerNation.type);
|
||||
$attackerNation.find('.form_tech').val(Math.floor(attackerNation.tech/1000));
|
||||
$attackerNation.find('.form_nation_level').val(attackerNation.level);
|
||||
if(attackerNation.capital == 1){
|
||||
$attackerNation.find('.form_is_capital:first').click();
|
||||
}
|
||||
else{
|
||||
$attackerNation.find('.form_is_capital:last').click();
|
||||
}
|
||||
$attackerNation.find('.form_city_level').val(attackerCity.level);
|
||||
|
||||
importGeneralInfo($('.attacker_form'), attackerGeneral);
|
||||
|
||||
$defenderNation.find('.form_nation_type').val(defenderNation.type);
|
||||
$defenderNation.find('.form_tech').val(Math.floor(defenderNation.tech/1000));
|
||||
$defenderNation.find('.form_nation_level').val(defenderNation.level);
|
||||
if(defenderNation.capital == 1){
|
||||
$defenderNation.find('.form_is_capital:first').click();
|
||||
}
|
||||
else{
|
||||
$defenderNation.find('.form_is_capital:last').click();
|
||||
}
|
||||
$defenderNation.find('.form_city_level').val(defenderCity.level);
|
||||
$('#city_def').val(defenderCity.def);
|
||||
$('#city_wall').val(defenderCity.wall);
|
||||
|
||||
$.each(defenderGenerals, function(idx, defenderGeneral){
|
||||
var $card = addDefender();
|
||||
importGeneralInfo($card, defenderGeneral);
|
||||
});
|
||||
}
|
||||
|
||||
var exportAllData = function(){
|
||||
var $attackerNation = $('.attacker_nation');
|
||||
var $defenderNation = $('.defender_nation');
|
||||
|
||||
var attackerGeneral = exportGeneralInfo($('.attacker_form'));
|
||||
|
||||
var attackerCity = {
|
||||
level:parseInt($attackerNation.find('.form_city_level').val()),
|
||||
};
|
||||
|
||||
var attackerNation = {
|
||||
type:parseInt($attackerNation.find('.form_nation_type').val()),
|
||||
tech:parseInt($attackerNation.find('.form_tech').val()) * 1000,
|
||||
level:parseInt($attackerNation.find('.form_nation_level').val()),
|
||||
capital:$attackerNation.find('.form_is_capital:checked').val()=='1'?1:2,
|
||||
}
|
||||
|
||||
var defenderGenerals = $('.defender_form').map(function(){
|
||||
return exportGeneralInfo($(this));
|
||||
}).toArray();
|
||||
|
||||
var defenderCity = {
|
||||
def: parseInt($('#city_def').val()),
|
||||
wall: parseInt($('#city_wall').val()),
|
||||
level:parseInt($defenderNation.find('.form_city_level').val()),
|
||||
};
|
||||
|
||||
var defenderNation = {
|
||||
type:parseInt($defenderNation.find('.form_nation_type').val()),
|
||||
tech:parseInt($defenderNation.find('.form_tech').val()) * 1000,
|
||||
level:parseInt($defenderNation.find('.form_nation_level').val()),
|
||||
capital:$defenderNation.find('.form_is_capital:checked').val()=='1'?3:4,
|
||||
}
|
||||
|
||||
var year = parseInt($('#year').val());
|
||||
var month = parseInt($('#month').val());
|
||||
var repeatCnt = parseInt($('#repeat_cnt').val());
|
||||
|
||||
return {
|
||||
attackerGeneral:attackerGeneral,
|
||||
attackerCity:attackerCity,
|
||||
attackerNation:attackerNation,
|
||||
|
||||
defenderGenerals:defenderGenerals,
|
||||
defenderCity:defenderCity,
|
||||
defenderNation:defenderNation,
|
||||
|
||||
year:year,
|
||||
month:month,
|
||||
repeatCnt:repeatCnt,
|
||||
};
|
||||
}
|
||||
|
||||
var extendAllDataForDB = function(allData){
|
||||
var defaultNation = {
|
||||
nation:0,
|
||||
name:'재야',
|
||||
capital:0,
|
||||
level:0,
|
||||
gold:0,
|
||||
rice:2000,
|
||||
type:0,
|
||||
tech:0,
|
||||
totaltech:0,
|
||||
gennum:200,
|
||||
};
|
||||
|
||||
var defaultCity = {
|
||||
nation:0,
|
||||
supply:1,
|
||||
name:'도시',
|
||||
|
||||
pop:500000,
|
||||
agri:10000,
|
||||
comm:10000,
|
||||
secu:10000,
|
||||
def:1000,
|
||||
wall:1000,
|
||||
|
||||
rate:100,
|
||||
|
||||
pop2:600000,
|
||||
agri2:12000,
|
||||
comm2:12000,
|
||||
secu2:10000,
|
||||
def2:12000,
|
||||
wall2:12000,
|
||||
|
||||
dead:0,
|
||||
|
||||
state:0,
|
||||
gen1:0,
|
||||
gen2:0,
|
||||
gen3:0,
|
||||
|
||||
conflict:'{}',
|
||||
};
|
||||
|
||||
var attackerNation = $.extend({}, defaultNation, allData.attackerNation);
|
||||
attackerNation.nation = 1;
|
||||
attackerNation.name = '출병국';
|
||||
attackerNation.totaltech = attackerNation.tech * attackerNation.gennum;
|
||||
|
||||
var attackerCity = $.extend({}, defaultCity, allData.attackerCity);
|
||||
attackerCity.nation = 1;
|
||||
attackerCity.city = 1;
|
||||
|
||||
var attackerGeneral = extendGeneralInfoForDB(allData.attackerGeneral);
|
||||
if(attackerGeneral.level == 4){
|
||||
attackerCity.gen1 = attackerGeneral.no;
|
||||
}
|
||||
if(attackerGeneral.level == 3){
|
||||
attackerCity.gen2 = attackerGeneral.no;
|
||||
}
|
||||
if(attackerGeneral.level == 2){
|
||||
attackerCity.gen3 = attackerGeneral.no;
|
||||
}
|
||||
|
||||
var defenderNation = $.extend({}, defaultNation, allData.defenderNation);
|
||||
defenderNation.nation = 2;
|
||||
defenderNation.name = '수비국';
|
||||
defenderNation.totaltech = defenderNation.tech * defenderNation.gennum;
|
||||
|
||||
var defenderCity = $.extend({}, defaultCity, allData.defenderCity);
|
||||
defenderCity.nation = 2;
|
||||
defenderCity.city = 3;
|
||||
defenderCity.wall2 = defenderCity.wall/5*6;
|
||||
defenderCity.def2 = defenderCity.def/5*6;
|
||||
|
||||
var defenderGenerals = [];
|
||||
$.each(allData.defenderGenerals, function(){
|
||||
var defenderGeneral = extendGeneralInfoForDB(this);
|
||||
if(defenderGeneral.level == 4){
|
||||
defenderCity.gen1 = defenderGeneral.no;
|
||||
}
|
||||
if(defenderGeneral.level == 3){
|
||||
defenderCity.gen2 = defenderGeneral.no;
|
||||
}
|
||||
if(defenderGeneral.level == 2){
|
||||
defenderCity.gen3 = defenderGeneral.no;
|
||||
}
|
||||
|
||||
defenderGenerals.push(defenderGeneral);
|
||||
});
|
||||
|
||||
|
||||
return $.extend({}, allData, {
|
||||
attackerGeneral:attackerGeneral,
|
||||
attackerCity:attackerCity,
|
||||
attackerNation:attackerNation,
|
||||
|
||||
defenderGenerals:defenderGenerals,
|
||||
defenderCity:defenderCity,
|
||||
defenderNation:defenderNation,
|
||||
});
|
||||
}
|
||||
|
||||
var parseSkillCount = function(skills){
|
||||
var result = [];
|
||||
$.each(skills, function(key, value){
|
||||
result.push("{0}({1}회)".format(key, toPretty(value)));
|
||||
})
|
||||
|
||||
if(result.length == 0){
|
||||
return '-';
|
||||
}
|
||||
return result.join(', ');
|
||||
}
|
||||
|
||||
var toPretty = function(number){
|
||||
if(isInt(number)){
|
||||
number = parseInt(number);
|
||||
}
|
||||
else{
|
||||
number = parseFloat(number).toFixed(2);
|
||||
}
|
||||
return numberWithCommas(number);
|
||||
}
|
||||
|
||||
var showBattleResult = function(result){
|
||||
$('#result_datetime').html(result.datetime);
|
||||
$('#result_warcnt').html(toPretty(result.avgWar));
|
||||
$('#result_phase').html(toPretty(result.phase));
|
||||
$('#result_killed').html(toPretty(result.killed));
|
||||
$('#result_dead').html(toPretty(result.dead));
|
||||
$('#result_attackerRice').html(toPretty(result.attackerRice));
|
||||
$('#result_defenderRice').html(toPretty(result.defenderRice));
|
||||
$('#result_attackerSkills').html(parseSkillCount(result.attackerSkills));
|
||||
|
||||
$('.result_defenderSkills').detach();
|
||||
|
||||
var $summary = $('#battle_result_summary');
|
||||
|
||||
$.each(result.defendersSkills, function(idx, defenderSkills){
|
||||
console.log(defenderSkills);
|
||||
var $result = $("<tr class='result_defenderSkills'><th>수비자{0} 스킬</th><td></td></tr>".format(idx + 1));
|
||||
$result.find('td').html(parseSkillCount(defenderSkills));
|
||||
$summary.append($result);
|
||||
});
|
||||
|
||||
$('#generalBattleResultLog').html(result.lastWarLog.generalBattleResultLog);
|
||||
$('#generalBattleDetailLog').html(result.lastWarLog.generalBattleDetailLog);
|
||||
|
||||
}
|
||||
|
||||
var beginBattle = function(){
|
||||
var data = extendAllDataForDB(exportAllData());
|
||||
console.log(data);
|
||||
$.ajax({
|
||||
type:'post',
|
||||
url:'j_simulate_battle.php',
|
||||
dataType:'json',
|
||||
data:{
|
||||
action:'battle',
|
||||
query:JSON.stringify(data),
|
||||
}
|
||||
}).then(function(result){
|
||||
console.log(result);
|
||||
if(!result.result){
|
||||
alert(result.reason);
|
||||
return;
|
||||
}
|
||||
showBattleResult(result);
|
||||
|
||||
}, function(result){
|
||||
alert('전투 개시 실패!');
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
var reorderDefender = function(defenderOrder){
|
||||
$.each(defenderOrder, function(idx, generalNo){
|
||||
|
||||
if(!(generalNo in defenderNoList)){
|
||||
//음..?
|
||||
alert("{0}이 수비자 리스트에 없습니다. 버그인 듯 합니다.".format(generalNo));
|
||||
return true;
|
||||
}
|
||||
|
||||
var $defenderObj = defenderNoList[generalNo];
|
||||
$defenderObj.detach();
|
||||
$defenderColumn.append($defenderObj);
|
||||
})
|
||||
}
|
||||
|
||||
var requestReorderDefender = function(){
|
||||
var data = extendAllDataForDB(exportAllData());
|
||||
console.log(data);
|
||||
$.ajax({
|
||||
type:'post',
|
||||
url:'j_simulate_battle.php',
|
||||
dataType:'json',
|
||||
data:{
|
||||
action:'reorder',
|
||||
query:JSON.stringify(data),
|
||||
}
|
||||
}).then(function(result){
|
||||
console.log(result);
|
||||
if(!result.result){
|
||||
alert(result.reason);
|
||||
return;
|
||||
}
|
||||
reorderDefender(result.order);
|
||||
|
||||
}, function(result){
|
||||
alert('재정렬 실패!');
|
||||
});
|
||||
}
|
||||
|
||||
initBasicEvent();
|
||||
$attackerCard.append($generalForm.clone(true,true));
|
||||
addDefender();
|
||||
|
||||
$('.btn-begin_battle').click(function(){
|
||||
beginBattle();
|
||||
});
|
||||
|
||||
$('.btn-reorder_defender').click(function(){
|
||||
requestReorderDefender();
|
||||
})
|
||||
});
|
||||
@@ -23,6 +23,14 @@ var escapeHtml = (function (string) {
|
||||
}
|
||||
})();
|
||||
|
||||
/**
|
||||
* 변수가 정수인지 확인하는 함수
|
||||
* @param {*} n 정수인지 확인하기 위한 인자
|
||||
* @return {boolean} 정수인지 여부
|
||||
*/
|
||||
function isInt(n) {
|
||||
return +n === n && !(n % 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* object의 array를 id를 key로 삼는 object로 재 변환
|
||||
@@ -89,6 +97,11 @@ function convColorValue(color) {
|
||||
|
||||
}
|
||||
|
||||
|
||||
function numberWithCommas(x) {
|
||||
return x.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",");
|
||||
}
|
||||
|
||||
/**
|
||||
* 단순한 Template 함수. <%변수명%>으로 template 가능
|
||||
* @see https://github.com/krasimir/absurd/blob/master/lib/processors/html/helpers/TemplateEngine.js
|
||||
|
||||
+27
-2
@@ -37,7 +37,7 @@ function processWar(array $rawAttacker, array $rawDefenderCity){
|
||||
|
||||
$city = new WarUnitCity($rawDefenderCity, $rawDefenderNation, $year, $month, $cityRate);
|
||||
|
||||
$defenderList = $db->query('SELECT no,name,nation,turntime,personal,special2,crew,crewtype,atmos,train,intel,intel2,book,power,power2,weap,injury,leader,leader2,horse,item,explevel,experience,dedication,level,gold,rice,dex0,dex10,dex20,dex30,dex40,warnum,killnum,deathnum,killcrew,deathcrew,recwar FROM general WHERE nation=%i AND city=%i AND nation!=0 and crew > 0 and rice>(crew/100) and ((train>=60 and atmos>=60 and mode=1) or (train>=80 and atmos>=80 and mode=2))', $city->getVar('nation'), $city->getVar('city'));
|
||||
$defenderList = $db->query('SELECT no,name,nation,turntime,personal,special2,crew,crewtype,atmos,train,intel,intel2,book,power,power2,weap,injury,leader,leader2,horse,item,explevel,experience,dedication,level,gold,rice,dex0,dex10,dex20,dex30,dex40,warnum,killnum,deathnum,killcrew,deathcrew,recwar,mode FROM general WHERE nation=%i AND city=%i AND nation!=0 and crew > 0 and rice>(crew/100) and ((train>=60 and atmos>=60 and mode=1) or (train>=80 and atmos>=80 and mode=2))', $city->getVar('nation'), $city->getVar('city'));
|
||||
|
||||
if(!$defenderList){
|
||||
$defenderList = [];
|
||||
@@ -63,7 +63,12 @@ function processWar(array $rawAttacker, array $rawDefenderCity){
|
||||
return null;
|
||||
}
|
||||
|
||||
$retVal = new WarUnitGeneral($iterDefender->current(), $rawDefenderCity, $rawDefenderNation, false, $year, $month);
|
||||
$rawGeneral = $iterDefender->current();
|
||||
if(extractBattleOrder($rawGeneral) <= 0){
|
||||
return null;
|
||||
}
|
||||
|
||||
$retVal = new WarUnitGeneral($rawGeneral, $rawDefenderCity, $rawDefenderNation, false, $year, $month);
|
||||
$iterDefender->next();
|
||||
return $retVal;
|
||||
};
|
||||
@@ -154,6 +159,26 @@ function processWar(array $rawAttacker, array $rawDefenderCity){
|
||||
}
|
||||
|
||||
function extractBattleOrder($general){
|
||||
if($general['crew'] == 0){
|
||||
return 0;
|
||||
}
|
||||
|
||||
if($general['rice'] <= $general['crew'] / 100){
|
||||
return 0;
|
||||
}
|
||||
|
||||
if($general['mode'] == 0){
|
||||
return 0;
|
||||
}
|
||||
|
||||
if($general['mode'] == 1 && ($general['train'] < 60 || $general['atmos'] < 60)){
|
||||
return 0;
|
||||
}
|
||||
|
||||
if($general['mode'] == 2 && ($general['train'] < 80 || $general['atmos'] < 80)){
|
||||
return 0;
|
||||
}
|
||||
|
||||
return (
|
||||
$general['leader'] +
|
||||
$general['power'] +
|
||||
|
||||
@@ -43,6 +43,16 @@ class ActionLogger{
|
||||
}
|
||||
|
||||
public function rollback(){
|
||||
$backup = [
|
||||
'generalHistoryLog'=>$this->generalHistoryLog,
|
||||
'generalActionLog'=>$this->generalActionLog,
|
||||
'generalBattleResultLog'=>$this->generalBattleResultLog,
|
||||
'generalBattleDetailLog'=>$this->generalBattleDetailLog,
|
||||
'nationalHistoryLog'=>$this->nationalHistoryLog,
|
||||
'globalHistoryLog'=>$this->globalHistoryLog,
|
||||
'globalActionLog'=>$this->globalActionLog,
|
||||
];
|
||||
|
||||
$this->generalHistoryLog = [];
|
||||
$this->generalActionLog = [];
|
||||
$this->generalBattleResultLog = [];
|
||||
@@ -50,6 +60,8 @@ class ActionLogger{
|
||||
$this->nationalHistoryLog = [];
|
||||
$this->globalHistoryLog = [];
|
||||
$this->globalActionLog = [];
|
||||
|
||||
return $backup;
|
||||
}
|
||||
|
||||
public function flush(){
|
||||
|
||||
+23
-2
@@ -28,11 +28,32 @@ class WarUnit{
|
||||
protected $warPowerMultiply = 1.0;
|
||||
|
||||
protected $activatedSkill = [];
|
||||
protected $logActivatedSkill = [];
|
||||
protected $isFinished = false;
|
||||
|
||||
private function __construct(){
|
||||
}
|
||||
|
||||
protected function clearActivatedSkill(){
|
||||
foreach($this->activatedSkill as $skillName=>$state){
|
||||
if(!$state){
|
||||
continue;
|
||||
}
|
||||
|
||||
if(!key_exists($skillName, $this->logActivatedSkill)){
|
||||
$this->logActivatedSkill[$skillName] = 1;
|
||||
}
|
||||
else{
|
||||
$this->logActivatedSkill[$skillName] += 1;
|
||||
}
|
||||
}
|
||||
$this->activatedSkill = [];
|
||||
}
|
||||
|
||||
function getActivatedSkillLog():array{
|
||||
return $this->logActivatedSkill;
|
||||
}
|
||||
|
||||
function getRaw():array{
|
||||
return $this->raw;
|
||||
}
|
||||
@@ -183,7 +204,7 @@ class WarUnit{
|
||||
$this->oppose = $oppose;
|
||||
$this->killedCurr = 0;
|
||||
$this->deadCurr = 0;
|
||||
$this->activatedSkill = [];
|
||||
$this->clearActivatedSkill();
|
||||
}
|
||||
|
||||
function getOppose():?WarUnit{
|
||||
@@ -312,7 +333,7 @@ class WarUnit{
|
||||
}
|
||||
|
||||
function beginPhase():void{
|
||||
$this->activatedSkill = [];
|
||||
$this->clearActivatedSkill();
|
||||
$this->computeWarPower();
|
||||
}
|
||||
|
||||
|
||||
@@ -90,6 +90,7 @@ class WarUnitCity extends WarUnit{
|
||||
if($this->isFinished){
|
||||
return;
|
||||
}
|
||||
$this->clearActivatedSkill();
|
||||
$this->isFinished = true;
|
||||
|
||||
$this->updateVar('def', Util::round($this->getHP() / 10));
|
||||
|
||||
@@ -954,6 +954,7 @@ class WarUnitGeneral extends WarUnit{
|
||||
if($this->isFinished){
|
||||
return;
|
||||
}
|
||||
$this->clearActivatedSkill();
|
||||
$this->isFinished = true;
|
||||
|
||||
$this->increaseVar('killcrew', $this->killed);
|
||||
|
||||
@@ -350,6 +350,8 @@ class Util extends \utilphp\util
|
||||
|
||||
shuffle($keys);
|
||||
|
||||
$new = [];
|
||||
|
||||
foreach($keys as $key) {
|
||||
$new[$key] = $array[$key];
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user