빙의 장수 기능 추가(선택은 미완)

This commit is contained in:
2018-05-05 19:51:56 +09:00
parent a534b8f812
commit 5974028c4d
5 changed files with 379 additions and 0 deletions
+2
View File
@@ -3,6 +3,7 @@
body {
color:white; background-color:black; font-family: '맑은 고딕';
}
table {
border: solid 1px; border-spacing: 0px; border-collapse: separate; border-top-color: gray; border-left-color: gray; border-right-color: black; border-bottom-color: black;
padding: 0px;
@@ -25,6 +26,7 @@ a.just_link {
}
.with_border{
margin:0;
border: solid 1px;
border-spacing: 0px;
border-collapse: separate;
+26
View File
@@ -0,0 +1,26 @@
.card_holder{
text-align:center;
}
.general_card{
width:100px;
display:inline-block;
}
.general_card label {
display: block;
padding-left: 15px;
text-indent: -15px;
}
.general_card input {
width: 13px;
height: 13px;
padding: 0;
margin:0;
vertical-align: bottom;
position: relative;
top: -1px;
*overflow: hidden;
}
+172
View File
@@ -0,0 +1,172 @@
<?php
namespace sammo;
include "lib.php";
include "func.php";
const VALID_MINUTE = 5;
const PICK_MORE_MINUTE = 2;
const KEEP_CNT = 3;
$refresh = Util::getReq('refresh', 'bool', false);
$keepResult = Util::getReq('keep', 'array_int', []);
$session = Session::requireLogin([])->setReadOnly();
$userID = Session::getUserID();
$oNow = new \DateTimeImmutable();
$now = $oNow->format('Y-m-d H:i:s');
$db = DB::db();
$oldGeneral = $db->queryFirstField('SELECT `no` FROM general WHERE `owner`=%i', $userID);
if($oldGeneral !== null){
Json::die([
'result'=>false,
'reason'=>'이미 장수가 생성되었습니다'
]);
}
list(
$year,
$month,
$maxgeneral,
$turnterm,
$genius,
$npcmode
) = $db->queryFirstList('SELECT year,month,maxgeneral,turnterm,genius,npcmode from game limit 1');
if(!$npcmode){
Json::die([
'result'=>false,
'reason'=>'빙의 가능한 서버가 아닙니다'
]);
}
$token = $db->queryFirstRow('SELECT * FROM select_npc_token WHERE `owner`=%i AND `valid_until`>=%s', $userID, $now);
$pickResult = [];
if($token && $refresh){
$pickMoreFrom = (new \DateTime($token['pick_more_from']))->getTimestamp();
$nowT = $oNow->getTimestamp();
if($nowT >= $pickMoreFrom){
$oldPickResult = Json::decode($token['pick_result']);
foreach($keepResult as $keepId){
if(\key_exists($keepId, $oldPickResult) && $oldPickResult[$keepId]['keepCnt'] > 0){
$pickResult[$keepId] = $oldPickResult[$keepId];
$pickResult[$keepId]['keepCnt']-=1;
}
}
if(count($pickResult) == count($oldPickResult)){
$refresh = false;
}
}
else{
Json::die([
'result'=>false,
'reason'=>'아직 다시 뽑을 수 없습니다',
]);
}
}
if($token && !$refresh){
Json::die([
'result'=>true,
'pick'=>Json::decode($token['pick_result']),
'pickMoreFrom'=>$token['pick_more_from'],
'validUntil'=>$token['valid_until']
]);
}
$candidates = [];
$weight = [];
foreach($db->query('SELECT `no`, `name`, leader, power, intel, imgsvr, picture, special, special2 FROM general WHERE npc=2') as $general){
$general['special'] = \sammo\SpecialityConst::DOMESTIC[$general['special']][0]??'-';
$general['special2'] = \sammo\SpecialityConst::WAR[$general['special2']][0]??'-';
$candidates[$general['no']] = $general + ['keepCnt'=>KEEP_CNT];
$allStat = $general['leader'] + $general['power'] + $general['intel'];
$weight[$general['no']] = pow($allStat, 1.7);
}
foreach($db->queryFirstColumn('SELECT pick_result FROM select_npc_token WHERE `owner`!=%i AND valid_until >=%s', $userID, $now) as $reserved){
$reserved = Json::decode($reserved);
foreach(array_keys($reserved) as $reservedNPC){
if(key_exists($reservedNPC, $weight)){
unset($candidates[$reservedNPC]);
unset($weight[$reservedNPC]);
}
}
}
$pickLimit = min(count($candidates), 5);
while(count($pickResult) < $pickLimit){
$generalID = Util::choiceRandomUsingWeight($weight);
if(!key_exists($generalID, $pickResult)){
$pickResult[$generalID] = $candidates[$generalID];
}
}
$newNonce = mt_rand(0, 0xfffffff);
$validMinute = max(VALID_MINUTE, intdiv($turnterm, 2));
$pickMoreMinute = max(PICK_MORE_MINUTE, intdiv($turnterm, 5));
$validUntil = $oNow->add(new \DateInterval(sprintf('PT%dM', $validMinute)));
$pickMoreFrom = $oNow->add(new \DateInterval(sprintf('PT%dM', $pickMoreMinute)));
$db->query('LOCK TABLES select_npc_token WRITE');
$db->delete('select_npc_token', 'valid_until < %s', $now);
$inserted = 0;
if($token){
$db->update('select_npc_token', [
'valid_until'=>$validUntil->format('Y-m-d H:i:s'),
'pick_more_from'=>$pickMoreFrom->format('Y-m-d H:i:s'),
'pick_result'=>Json::encode($pickResult),
'nonce'=>$newNonce
], 'owner = %i AND nonce = %i', $userID, $token['nonce']);
if($db->affectedRows()){
$inserted = -1;
}
}
else{
$db->insertIgnore('select_npc_token', [
'owner'=>$userID,
'valid_until'=>$validUntil->format('Y-m-d H:i:s'),
'pick_more_from'=>'2000-01-01 01:00:00',
'pick_result'=>Json::encode($pickResult),
'nonce'=>$newNonce
]);
if($db->affectedRows()){
$inserted = 1;
}
}
$db->query('UNLOCK TABLES');
if($inserted === 0){
Json::die([
'result'=>false,
'reason'=>'중복 요청, 다시 랜덤 토큰을 확인해주세요'
]);
}
Json::die([
'result'=>true,
'pick'=>$pickResult,
'pickMoreFrom'=>($inserted===-1)?$pickMoreFrom->format('Y-m-d H:i:s'):'2000-01-01 01:00:00',
'validUntil'=>$validUntil->format('Y-m-d H:i:s')
]);
+76
View File
@@ -0,0 +1,76 @@
var templateGeneralCard =
'<div class="general_card">\
<h4 class="bg1 with_border"><%name%></h4>\
<h4><img src="<%iconPath%>" height=64 width=64></h4>\
<p><%leader%> / <%power%> / <%intel%><br>\
<%special%> / <%special2%></p>\
<button type="subject" class="with_skin with_border select_btn" value="<%no%>" name="pick">빙의하기</button>\
<label><input <%keepCnt?"":disabled="disabled"%> type="checkbox" value="<%no%>" name="keep[]" class="keep_select">보관(<%keepCnt%>회)</label>\
</div>';
function updatePickMoreTimer(){
var $btn = $('#btn_pick_more');
var now = Date.now();
var remain = ($btn.data('available') - now) / 1000;
if(remain <= 0){
$btn.prop('disabled', false)
$btn.html('다른 장수 보기');
return;
}
$btn.html('다른 장수 보기({0}초)'.format(Math.ceil(remain)));
setTimeout(updatePickMoreTimer, 250);
}
function printGenerals(value){
$('.card_holder').empty();
$('#valid_until_text').html(value.validUntil);
$('#btn_pick_more').data('available', new Date(value.pickMoreFrom).getTime()).prop('disabled',true);
$.each(value.pick, function(idx, cardData){
cardData.iconPath = getIconPath(cardData.imgsvr, cardData.picture);
console.log(cardData);
var $card = $(TemplateEngine(templateGeneralCard, cardData));
console.log($card);
$('.card_holder').append($card);
});
updatePickMoreTimer();
}
jQuery(function($){
$.post('j_get_select_npc_token.php').then(function(value){
if(!value.result){
alert(value.reason);
return;
}
console.log(value);
printGenerals(value);
});
$('#btn_pick_more').click(function(){
var generals = $.map($('.keep_select:checked'), function(value){
return $(value).val();
});
console.log(generals);
$.post({
url:'j_get_select_npc_token.php',
dataType:'json',
data:{
refresh:true,
keep:generals
}
}).then(function(result){
if(!result.result){
alert(result.reason);
location.refresh();
}
printGenerals(result);
});
});
});
+103
View File
@@ -0,0 +1,103 @@
<?php
namespace sammo;
include "lib.php";
include "func.php";
$session = Session::requireLogin()->setReadOnly();
$userID = Session::getUserID();
$rootDB = RootDB::db();
$db = DB::db();
//회원 테이블에서 정보확인
$member = $rootDB->queryFirstRow('select no,name,picture,grade from member where no=%i', $userID);
if(!$member) {
$session->logout();
header('location:..');
die();
}
list($npcmode, $maxgeneral) = $db->queryFirstList('SELECT npcmode,maxgeneral FROM game LIMIT 1');
if(!$npcmode) {
header('location:..');
die();
}
$gencount = $db->queryFirstField('SELECT count(`no`) FROM general WHERE npc<2');
$nations = $db->queryAllLists('SELECT `name`, scoutmsg, color FROM nation');
?>
<!DOCTYPE html>
<html>
<head>
<title><?=UniqueConst::$serverName?>: NPC빙의</title>
<meta HTTP-EQUIV='Content-Type' CONTENT='text/html; charset=utf-8'>
<link rel='stylesheet' href='css/normalize.css' type='text/css'>
<link rel='stylesheet' href='../d_shared/common.css' type='text/css'>
<link rel='stylesheet' href='../css/config.css' type='text/css'>
<link rel='stylesheet' href='css/common.css' type='text/css'>
<link rel='stylesheet' href='css/select_npc.css' type='text/css'>
<script type="text/javascript" src="../d_shared/common_path.js"></script>
<script type="text/javascript" src="../js/common.js"></script>
<script type="text/javascript" src="../e_lib/jquery-3.2.1.min.js"></script>
<script src="js/select_npc.js"></script>
</head>
<?php
if ($gencount >= $maxgeneral) {
?>
<body>
<script>
alert('더 이상 등록할 수 없습니다.');
history.go(-1);
</script>
</body>
</html>
<?php
die();
}
?>
<body>
<div class="container">
<div class="bg0 with_border legacy_layout">장 수 선 택<br><?=backButton()?></div>
<table style="width:100%;" class="bg0 with_border">
<tr><td><?=info(0)?></td></tr>
</table>
<table style="width:100%;" class="bg0 with_border">
<thead>
<tr><th colspan=2 class="bg1">임관 권유 메세지</th></tr>
</thead>
<tbody>
<?php foreach($nations as list($name, $scoutmsg, $color)): ?>
<tr>
<td style='width:98px;color:<?=newColor($color)?>;background-color:<?=$color?>'><?=$name?></td>
<td style='color:<?=newColor($color)?>;background-color:<?=$color?>'><?=$scoutmsg?:'-'?></td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
<div class="bg0">
<div class="bg1 with_border legacy_layout font1" style="text-align:center;font-weight:bold;">장수 빙의</div>
<div class="with_border legacy_layout" style="text-align:center;">
<small id="valid_until">(<span id="valid_until_text"></span> 까지 유효)</small><br>
<form class="card_holder">
</form>
</div>
<div class="with_border legacy_layout" style="text-align:center">
<button id="btn_pick_more" disabled="disabled" class="with_skin with_border">다른 장수 보기</button><br>
</div>
<div class="with_border legacy_layout"><?=backButton()?></div>
<div class="with_border legacy_layout"><?=banner()?></div>
</div>
</div>
</body>
</html>