feat: 전투 시뮬레이터에 히든 버프 반영 가능

This commit is contained in:
2023-02-24 00:25:29 +09:00
parent 87e57aea0e
commit 7a3642296a
3 changed files with 1059 additions and 971 deletions
+19
View File
@@ -434,6 +434,25 @@ if ($nationID) {
</div> </div>
<input type="number" class="form-control form_killcrew" value="0" step="1"> <input type="number" class="form-control form_killcrew" value="0" step="1">
</div> </div>
<div class="input-group mb-0">
<div class="input-group-text">자신</div>
<div class="input-group-text">회피 확률</div>
<input type="number" class="form-control form_war_avoid_ratio" value="0" step="1" min="0" max="5">
<div class="input-group-text">필살 확률</div>
<input type="number" class="form-control form_war_critical_ratio" value="0" step="1" min="0" max="5">
<div class="input-group-text">계략 시도 확률</div>
<input type="number" class="form-control form_war_magic_trial_prob" value="0" step="1" min="0" max="5">
</div>
<div class="input-group mb-1">
<div class="input-group-text">상대</div>
<div class="input-group-text">회피 확률</div>
<input type="number" class="form-control form_oppose_war_avoid_ratio" value="0" step="1" min="0" max="5">
<div class="input-group-text">필살 확률</div>
<input type="number" class="form-control form_oppose_war_critical_ratio" value="0" step="1" min="0" max="5">
<div class="input-group-text">계략 시도 확률</div>
<input type="number" class="form-control form_oppose_war_magic_trial_prob" value="0" step="1" min="0" max="5">
</div>
</div> </div>
</div> </div>
+40
View File
@@ -133,6 +133,19 @@ $generalCheck = [
['weapon', array_merge(array_keys(GameConst::$allItems['weapon']), ['None'])], ['weapon', array_merge(array_keys(GameConst::$allItems['weapon']), ['None'])],
['book', array_merge(array_keys(GameConst::$allItems['book']), ['None'])], ['book', array_merge(array_keys(GameConst::$allItems['book']), ['None'])],
['item', array_merge(array_keys(GameConst::$allItems['item']), ['None'])], ['item', array_merge(array_keys(GameConst::$allItems['item']), ['None'])],
],
'array'=>['inheritBuff'],
];
$inheritBuffCheck = [
'between'=>[
[TriggerInheritBuff::WAR_AVOID_RATIO, [0, 5]],
[TriggerInheritBuff::WAR_CRITICAL_RATIO, [0, 5]],
[TriggerInheritBuff::WAR_MAGIC_TRIAL_PROB, [0, 5]],
[TriggerInheritBuff::OPPOSE_WAR_AVOID_RATIO, [0, 5]],
[TriggerInheritBuff::OPPOSE_WAR_CRITICAL_RATIO, [0, 5]],
[TriggerInheritBuff::OPPOSE_WAR_MAGIC_TRIAL_PROB, [0, 5]],
] ]
]; ];
@@ -144,6 +157,19 @@ if(!$v->validate()){
'reason'=>'[출병자]'.$v->errorStr() 'reason'=>'[출병자]'.$v->errorStr()
]); ]);
} }
$rawAttacker['aux'] = [];
if(key_exists('inheritBuff', $rawAttacker)){
$v = new Validator($rawAttacker['inheritBuff']);
$v->rules($inheritBuffCheck);
if(!$v->validate()){
Json::die([
'result'=>false,
'reason'=>'[출병자]'.$v->errorStr()
]);
}
$rawAttacker['aux']['inheritBuff'] = $rawAttacker['inheritBuff'];
}
$rawAttacker['aux'] = Json::encode($rawAttacker['aux']);
$rawAttacker['owner'] = 0; $rawAttacker['owner'] = 0;
$defenderList = []; $defenderList = [];
@@ -157,6 +183,20 @@ foreach($rawDefenderList as $idx=>$rawDefenderGeneral){
'reason'=>"[수비자{$idx}]".$v->errorStr() 'reason'=>"[수비자{$idx}]".$v->errorStr()
]); ]);
} }
$rawDefenderGeneral['aux'] = [];
if(key_exists('inheritBuff', $rawDefenderGeneral)){
$v = new Validator($rawDefenderGeneral['inheritBuff']);
$v->rules($inheritBuffCheck);
if(!$v->validate()){
$idx+=1;
Json::die([
'result'=>false,
'reason'=>"[수비자{$idx}]".$v->errorStr()
]);
}
$rawDefenderGeneral['aux']['inheritBuff'] = $rawDefenderGeneral['inheritBuff'];
}
$rawDefenderGeneral['aux'] = Json::encode($rawDefenderGeneral['aux']);
$rawDefenderGeneral['owner'] = 0; $rawDefenderGeneral['owner'] = 0;
$defenderList[] = new General($rawDefenderGeneral, extractRankVar($rawDefenderGeneral), $rawDefenderCity, $rawAttackerNation, $year, $month, true); $defenderList[] = new General($rawDefenderGeneral, extractRankVar($rawDefenderGeneral), $rawDefenderCity, $rawAttackerNation, $year, $month, true);
+999 -970
View File
@@ -1,1079 +1,1108 @@
import $ from 'jquery'; import $ from "jquery";
import 'bootstrap'; import "bootstrap";
import download from 'downloadjs'; import download from "downloadjs";
import { unwrap } from "@util/unwrap"; import { unwrap } from "@util/unwrap";
import { isInteger } from 'lodash-es'; import { isInteger } from "lodash-es";
import { errUnknown } from '@/common_legacy'; import { errUnknown } from "@/common_legacy";
import { getNPCColor } from './utilGame'; import { getNPCColor } from "./utilGame";
import { combineArray } from "@util/combineArray"; import { combineArray } from "@util/combineArray";
import { isBrightColor } from "@util/isBrightColor"; import { isBrightColor } from "@util/isBrightColor";
import { numberWithCommas } from "@util/numberWithCommas"; import { numberWithCommas } from "@util/numberWithCommas";
import { unwrap_any } from '@util/unwrap_any'; import { unwrap_any } from "@util/unwrap_any";
import type { BasicGeneralListResponse, InvalidResponse } from '@/defs'; import type { BasicGeneralListResponse, InvalidResponse } from "@/defs";
import { formatTime } from '@util/formatTime'; import { formatTime } from "@util/formatTime";
import { Modal } from 'bootstrap'; import { Modal } from "bootstrap";
type CityAttackerInfo = { type CityAttackerInfo = {
level: number, level: number;
} };
type CityBasicInfo = { type CityBasicInfo = {
nation?: number, nation?: number;
level: number, level: number;
def: number, def: number;
wall: number, wall: number;
city?: number, city?: number;
} };
type NationBasicInfo = { type NationBasicInfo = {
level: number, level: number;
type: string, type: string;
tech: number, tech: number;
capital: number, capital: number;
} };
type InheritBuff = {
warAvoidRatio: number;
warCriticalRatio: number;
warMagicTrialProb: number;
warAvoidRatioOppose: number;
warCriticalRatioOppose: number;
warMagicTrialProbOppose: number;
};
type GeneralInfo = { type GeneralInfo = {
no: number, no: number;
npc?: number npc?: number;
name: string, name: string;
officer_level: number, officer_level: number;
explevel: number, explevel: number;
leadership: number, leadership: number;
horse: string, horse: string;
strength: number, strength: number;
weapon: string, weapon: string;
intel: number, intel: number;
book: string, book: string;
item: string, item: string;
injury: number, injury: number;
rice: number, rice: number;
personal: string, personal: string;
special2: string, special2: string;
crew: number, crew: number;
crewtype: number, crewtype: number;
atmos: number, atmos: number;
train: number, train: number;
dex1: number, dex1: number;
dex2: number, dex2: number;
dex3: number, dex3: number;
dex4: number, dex4: number;
dex5: number, dex5: number;
defence_train: number, defence_train: number;
warnum: number, warnum: number;
killnum: number, killnum: number;
killcrew: number, killcrew: number;
officer_city?: number, officer_city?: number;
inheritBuff?: InheritBuff;
}; };
type BattleInfo = { type BattleInfo = {
attackerGeneral: GeneralInfo, attackerGeneral: GeneralInfo;
attackerCity: CityAttackerInfo | CityBasicInfo, attackerCity: CityAttackerInfo | CityBasicInfo;
attackerNation: NationBasicInfo, attackerNation: NationBasicInfo;
defenderGenerals: GeneralInfo[], defenderGenerals: GeneralInfo[];
defenderCity: CityBasicInfo, defenderCity: CityBasicInfo;
defenderNation: NationBasicInfo, defenderNation: NationBasicInfo;
year: number, year: number;
month: number, month: number;
repeatCnt: number, repeatCnt: number;
seed?: string, seed?: string;
}; };
type ExportedGeneralInfo = { type ExportedGeneralInfo = {
objType: 'general', objType: "general";
data: GeneralInfo, data: GeneralInfo;
} };
type ExportedBattleInfo = { type ExportedBattleInfo = {
objType: 'battle', objType: "battle";
data: BattleInfo data: BattleInfo;
} };
type ExportedInfo = ExportedGeneralInfo | ExportedBattleInfo; type ExportedInfo = ExportedGeneralInfo | ExportedBattleInfo;
type BattleResult = { type BattleResult = {
result: true, result: true;
datetime: string, datetime: string;
lastWarLog: { lastWarLog: {
generalBattleResultLog: string, generalBattleResultLog: string;
generalBattleDetailLog: string, generalBattleDetailLog: string;
}, };
avgWar: number, avgWar: number;
phase: number, phase: number;
killed: number, killed: number;
maxKilled: number, maxKilled: number;
minKilled: number, minKilled: number;
dead: number, dead: number;
maxDead: number, maxDead: number;
minDead: number, minDead: number;
attackerRice: number, attackerRice: number;
defenderRice: number, defenderRice: number;
attackerSkills: Record<string, number>, attackerSkills: Record<string, number>;
defendersSkills: Record<string, number>[], defendersSkills: Record<string, number>[];
} };
declare global { declare global {
interface Window { interface Window {
nation?: NationBasicInfo, nation?: NationBasicInfo;
city?: CityBasicInfo, city?: CityBasicInfo;
defaultSpecialDomestic: string, defaultSpecialDomestic: string;
} }
} }
let modalImport: Modal|undefined = undefined; let modalImport: Modal | undefined = undefined;
$(function ($) { $(function ($) {
const $generalForm = $(".form_sample .general_detail");
const $defenderHeaderForm = $(".form_sample .card-header");
const $defenderColumn = $(".defender-column");
const defenderNoList: Record<number, JQuery<HTMLElement>> = {};
const $generalForm = $('.form_sample .general_detail'); const $attackerCard = $(".attacker_form");
const $defenderHeaderForm = $('.form_sample .card-header');
const $defenderColumn = $('.defender-column');
const defenderNoList: Record<number, JQuery<HTMLElement>> = {}; const initBasicEvent = function () {
if (window.nation && window.city) {
const $attackerCard = $('.attacker_form'); $(".form_city_level").val(window.city.level);
$(".form_def").val(window.city.def);
const initBasicEvent = function () { $(".form_wall").val(window.city.wall);
$(".form_nation_type").val(window.nation.type);
if (window.nation && window.city) { $(".form_nation_level").val(window.nation.level);
$('.form_city_level').val(window.city.level); $(".form_tech").val(window.nation.tech / 1000);
$('.form_def').val(window.city.def); if (window.nation.capital == window.city.city) {
$('.form_wall').val(window.city.wall); $(".attacker_nation .form_is_capital:first").trigger("click");
$('.form_nation_type').val(window.nation.type); $(".defender_nation .form_is_capital:first").trigger("click");
$('.form_nation_level').val(window.nation.level); } else {
$('.form_tech').val(window.nation.tech / 1000); $(".attacker_nation .form_is_capital:last").trigger("click");
if (window.nation.capital == window.city.city) { $(".defender_nation .form_is_capital:last").trigger("click");
$('.attacker_nation .form_is_capital:first').trigger('click'); }
$('.defender_nation .form_is_capital:first').trigger('click'); } else {
} else { $(".attacker_nation .form_is_capital:last").trigger("click");
$('.attacker_nation .form_is_capital:last').trigger('click'); $(".defender_nation .form_is_capital:last").trigger("click");
$('.defender_nation .form_is_capital:last').trigger('click');
}
} else {
$('.attacker_nation .form_is_capital:last').trigger('click');
$('.defender_nation .form_is_capital:last').trigger('click');
}
$('.form_injury').on('change', function () {
const $this = $(this) as JQuery<HTMLInputElement>;
const $general = getGeneralDetail($this);
const $helptext = $general.find('.injury_helptext');
const injury = parseInt($this.val() as string);
//FIXME: PHP 코드와 항상 일치하도록 변경
let text = '건강';
let 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').on('click', function () {
const $btn = $(this);
const $general = getGeneralDetail($btn);
const values = exportGeneralInfo($general);
console.log(values);
});
$('.delete-defender').on('click', function () {
const $card = getGeneralFrame($(this));
deleteDefender($card);
});
$('.copy-defender').on('click', function () {
const $card = getGeneralFrame($(this));
copyDefender($card);
});
$('.add-defender').on('click', function () {
addDefender();
});
$('.btn-general-load').on('click', function () {
const $file = $(this).prev();
$file[0].click();
})
$<HTMLInputElement>('.form_load_general_file').on('change', function (e) {
e.preventDefault();
const $this = $(this);
const $card = getGeneralFrame($this);
const files = unwrap(e.target.files);
importGeneralInfoByFile(files, $card);
return false;
});
$('.btn-general-import-server').on('click', function () {
const $this = $(this);
const $card = getGeneralFrame($this);
const $modal = $('#importModal');
$modal.data('target', $card);
if(!modalImport){
modalImport = new Modal($modal[0]);
}
modalImport.show();
});
$('.btn-general-save').on('click', function () {
const $this = $(this);
const $general = getGeneralDetail($this);
const generalData = exportGeneralInfo($general);
const filename = `general_${generalData.name}.json`;
const saveData = JSON.stringify({
objType: 'general',
data: generalData
}, null, 4);
download(saveData, filename, 'application/json');
});
$('.btn-battle-load').on('click', function () {
const $file = $(this).prev();
$file[0].click();
})
$<HTMLInputElement>('.form_load_battle_file').on('change', function (e) {
e.preventDefault();
const files = unwrap(e.target.files);
importBattleInfoByFile(files);
return false;
});
$('.btn-battle-save').on('click', function () {
const battleData = exportAllData();
const dateText = formatTime(new Date(), 'yyyyMMdd_HHmmss');
const filename = `battle_${dateText}.json`;
const saveData = JSON.stringify({
objType: 'battle',
data: battleData
}, null, 4);
download(saveData, filename, 'application/json');
})
const $generals = $('.general_detail');
$generals.on('dragover dragleave', function (e) {
e.stopPropagation()
e.preventDefault()
})
$generals.on('drop', function (e) {
e.preventDefault();
const $this = $(this);
const $card = getGeneralFrame($this);
const files = unwrap((unwrap(e.originalEvent) as DragEvent).dataTransfer).files;
importGeneralInfoByFile(files, $card);
return false;
});
const $battlePad = $('.dragpad_battle');
$battlePad.on('dragover dragleave', function (e) {
e.stopPropagation()
e.preventDefault()
})
$battlePad.on('drop', function (e) {
e.preventDefault();
const files = unwrap((unwrap(e.originalEvent) as DragEvent).dataTransfer).files;
importBattleInfoByFile(files);
return false;
});
} }
const importGeneralInfo = function ($general: JQuery<HTMLElement>, data: GeneralInfo) { $(".form_injury").on("change", function () {
const setVal = function (query: string, val: string | number) { const $this = $(this) as JQuery<HTMLInputElement>;
$general.find(query).val(val).trigger('change'); const $general = getGeneralDetail($this);
} const $helptext = $general.find(".injury_helptext");
setVal('.form_general_name', data.name); const injury = parseInt($this.val() as string);
//FIXME: PHP 코드와 항상 일치하도록 변경
let text = "건강";
let 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);
});
setVal('.form_officer_level', data.officer_level); $(".export_general").on("click", function () {
setVal('.form_exp_level', data.explevel); const $btn = $(this);
const $general = getGeneralDetail($btn);
setVal('.form_leadership', data.leadership); const values = exportGeneralInfo($general);
setVal('.form_general_horse', data.horse); console.log(values);
setVal('.form_strength', data.strength); });
setVal('.form_general_weap', data.weapon); $(".delete-defender").on("click", function () {
setVal('.form_intel', data.intel); const $card = getGeneralFrame($(this));
setVal('.form_general_book', data.book); deleteDefender($card);
setVal('.form_general_item', data.item); });
$(".copy-defender").on("click", function () {
const $card = getGeneralFrame($(this));
copyDefender($card);
});
setVal('.form_injury', data.injury); $(".add-defender").on("click", function () {
addDefender();
});
setVal('.form_rice', data.rice); $(".btn-general-load").on("click", function () {
const $file = $(this).prev();
$file[0].click();
});
setVal('.form_general_character', data.personal); $<HTMLInputElement>(".form_load_general_file").on("change", function (e) {
setVal('.form_general_special_war', data.special2); e.preventDefault();
const $this = $(this);
const $card = getGeneralFrame($this);
setVal('.form_crew', data.crew); const files = unwrap(e.target.files);
setVal('.form_crewtype', data.crewtype);
setVal('.form_atmos', data.atmos);
setVal('.form_train', data.train);
setVal('.form_dex1', data.dex1); importGeneralInfoByFile(files, $card);
setVal('.form_dex2', data.dex2); return false;
setVal('.form_dex3', data.dex3); });
setVal('.form_dex4', data.dex4);
setVal('.form_dex5', data.dex5);
setVal('.form_defence_train', data.defence_train);
setVal('.form_warnum', data.warnum); $(".btn-general-import-server").on("click", function () {
setVal('.form_killnum', data.killnum); const $this = $(this);
setVal('.form_killcrew', data.killcrew); const $card = getGeneralFrame($this);
if (!setGeneralNo($general, data.no)) { const $modal = $("#importModal");
setGeneralNo($general, generateNewGeneralNo()); $modal.data("target", $card);
} if (!modalImport) {
modalImport = new Modal($modal[0]);
}
modalImport.show();
});
$(".btn-general-save").on("click", function () {
const $this = $(this);
const $general = getGeneralDetail($this);
const generalData = exportGeneralInfo($general);
const filename = `general_${generalData.name}.json`;
const saveData = JSON.stringify(
{
objType: "general",
data: generalData,
},
null,
4
);
download(saveData, filename, "application/json");
});
$(".btn-battle-load").on("click", function () {
const $file = $(this).prev();
$file[0].click();
});
$<HTMLInputElement>(".form_load_battle_file").on("change", function (e) {
e.preventDefault();
const files = unwrap(e.target.files);
importBattleInfoByFile(files);
return false;
});
$(".btn-battle-save").on("click", function () {
const battleData = exportAllData();
const dateText = formatTime(new Date(), "yyyyMMdd_HHmmss");
const filename = `battle_${dateText}.json`;
const saveData = JSON.stringify(
{
objType: "battle",
data: battleData,
},
null,
4
);
download(saveData, filename, "application/json");
});
const $generals = $(".general_detail");
$generals.on("dragover dragleave", function (e) {
e.stopPropagation();
e.preventDefault();
});
$generals.on("drop", function (e) {
e.preventDefault();
const $this = $(this);
const $card = getGeneralFrame($this);
const files = unwrap((unwrap(e.originalEvent) as DragEvent).dataTransfer).files;
importGeneralInfoByFile(files, $card);
return false;
});
const $battlePad = $(".dragpad_battle");
$battlePad.on("dragover dragleave", function (e) {
e.stopPropagation();
e.preventDefault();
});
$battlePad.on("drop", function (e) {
e.preventDefault();
const files = unwrap((unwrap(e.originalEvent) as DragEvent).dataTransfer).files;
importBattleInfoByFile(files);
return false;
});
};
const importGeneralInfo = function ($general: JQuery<HTMLElement>, data: GeneralInfo) {
const setVal = function (query: string, val: string | number) {
$general.find(query).val(val).trigger("change");
};
setVal(".form_general_name", data.name);
setVal(".form_officer_level", data.officer_level);
setVal(".form_exp_level", data.explevel);
setVal(".form_leadership", data.leadership);
setVal(".form_general_horse", data.horse);
setVal(".form_strength", data.strength);
setVal(".form_general_weap", data.weapon);
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_dex1", data.dex1);
setVal(".form_dex2", data.dex2);
setVal(".form_dex3", data.dex3);
setVal(".form_dex4", data.dex4);
setVal(".form_dex5", data.dex5);
setVal(".form_defence_train", data.defence_train);
setVal(".form_warnum", data.warnum);
setVal(".form_killnum", data.killnum);
setVal(".form_killcrew", data.killcrew);
if (data.inheritBuff) {
setVal(".form_war_avoid_ratio", data.inheritBuff.warAvoidRatio);
setVal(".form_war_critical_ratio", data.inheritBuff.warCriticalRatio);
setVal(".form_war_magic_trial_prob", data.inheritBuff.warMagicTrialProb);
setVal(".form_oppose_war_avoid_ratio", data.inheritBuff.warAvoidRatioOppose);
setVal(".form_oppose_war_critical_ratio", data.inheritBuff.warCriticalRatioOppose);
setVal(".form_oppose_war_magic_trial_prob", data.inheritBuff.warMagicTrialProbOppose);
} }
const exportGeneralInfo = function ($general: JQuery<HTMLElement>): GeneralInfo { if (!setGeneralNo($general, data.no)) {
const getInt = function (query: string): number { setGeneralNo($general, generateNewGeneralNo());
return parseInt(unwrap_any<string>($general.find(query).val())); }
} };
const getVal = function (query: string): string { const exportGeneralInfo = function ($general: JQuery<HTMLElement>): GeneralInfo {
return unwrap_any<string>($general.find(query).val()); const getInt = function (query: string): number {
} return parseInt(unwrap_any<string>($general.find(query).val()));
};
return { const getVal = function (query: string): string {
no: getGeneralNo($general), return unwrap_any<string>($general.find(query).val());
name: getVal('.form_general_name'), };
officer_level: getInt('.form_officer_level'),
explevel: getInt('.form_exp_level'),
leadership: getInt('.form_leadership'), return {
horse: getVal('.form_general_horse'), no: getGeneralNo($general),
strength: getInt('.form_strength'), name: getVal(".form_general_name"),
weapon: getVal('.form_general_weap'), officer_level: getInt(".form_officer_level"),
intel: getInt('.form_intel'), explevel: getInt(".form_exp_level"),
book: getVal('.form_general_book'),
item: getVal('.form_general_item'),
injury: getInt('.form_injury'), leadership: getInt(".form_leadership"),
horse: getVal(".form_general_horse"),
strength: getInt(".form_strength"),
weapon: getVal(".form_general_weap"),
intel: getInt(".form_intel"),
book: getVal(".form_general_book"),
item: getVal(".form_general_item"),
rice: getInt('.form_rice'), injury: getInt(".form_injury"),
personal: getVal('.form_general_character'), rice: getInt(".form_rice"),
special2: getVal('.form_general_special_war'),
crew: getInt('.form_crew'), personal: getVal(".form_general_character"),
crewtype: getInt('.form_crewtype'), special2: getVal(".form_general_special_war"),
atmos: getInt('.form_atmos'),
train: getInt('.form_train'),
dex1: getInt('.form_dex1'), crew: getInt(".form_crew"),
dex2: getInt('.form_dex2'), crewtype: getInt(".form_crewtype"),
dex3: getInt('.form_dex3'), atmos: getInt(".form_atmos"),
dex4: getInt('.form_dex4'), train: getInt(".form_train"),
dex5: getInt('.form_dex5'),
defence_train: getInt('.form_defence_train'), dex1: getInt(".form_dex1"),
dex2: getInt(".form_dex2"),
dex3: getInt(".form_dex3"),
dex4: getInt(".form_dex4"),
dex5: getInt(".form_dex5"),
warnum: getInt('.form_warnum'), defence_train: getInt(".form_defence_train"),
killnum: getInt('.form_killnum'),
killcrew: getInt('.form_killcrew'),
}; warnum: getInt(".form_warnum"),
killnum: getInt(".form_killnum"),
killcrew: getInt(".form_killcrew"),
inheritBuff: {
warAvoidRatio: getInt(".form_war_avoid_ratio"),
warCriticalRatio: getInt(".form_war_critical_ratio"),
warMagicTrialProb: getInt(".form_war_magic_trial_prob"),
warAvoidRatioOppose: getInt(".form_oppose_war_avoid_ratio"),
warCriticalRatioOppose: getInt(".form_oppose_war_critical_ratio"),
warMagicTrialProbOppose: getInt(".form_oppose_war_magic_trial_prob"),
},
};
};
const importBattleInfoByFile = function (files: FileList) {
if (files === null) {
alert("파일 에러!");
return false;
} }
const importBattleInfoByFile = function (files: FileList) { if (files.length < 1) {
if (files === null) { alert("파일 에러!");
alert('파일 에러!'); return false;
return false; }
}
if (files.length < 1) { const file = files[0];
alert("파일 에러!"); if (file.size > 1024 * 1024) {
return false; alert("파일이 너무 큽니다!");
} return false;
}
if (file.type === "") {
alert("폴더를 업로드할 수 없습니다!");
return false;
}
const reader = new FileReader();
reader.onload = function () {
let battleData: ExportedInfo;
try {
battleData = JSON.parse(unwrap_any<string>(reader.result));
} catch (e) {
alert("올바르지 않은 파일 형식입니다");
return false;
}
const file = files[0]; if (!("objType" in battleData)) {
if (file.size > 1024 * 1024) { alert("파일 형식을 확인할 수 없습니다");
alert('파일이 너무 큽니다!'); return false;
return false; }
}
if (file.type === '') {
alert('폴더를 업로드할 수 없습니다!');
return false;
}
const reader = new FileReader(); if (battleData.objType != "battle") {
reader.onload = function () { alert("전투 데이터가 아닙니다");
let battleData: ExportedInfo; return false;
try { }
battleData = JSON.parse(unwrap_any<string>(reader.result));
} catch (e) {
alert('올바르지 않은 파일 형식입니다');
return false;
}
if (!('objType' in battleData)) { importBattleInfo(battleData.data);
alert('파일 형식을 확인할 수 없습니다'); return true;
return false; };
}
if (battleData.objType != 'battle') { try {
alert('전투 데이터가 아닙니다'); reader.readAsText(file);
return false; } catch (e) {
} alert("파일을 읽는데 실패했습니다.");
return false;
}
importBattleInfo(battleData.data); return true;
return true; };
};
try { const importGeneralInfoByFile = function (files: FileList, $card: JQuery<HTMLElement>) {
if ($card === undefined) {
$card = addDefender();
}
reader.readAsText(file); if (files === null) {
} catch (e) { alert("파일 에러!");
alert('파일을 읽는데 실패했습니다.'); return false;
return false; }
}
if (files.length < 1) {
alert("파일 에러!");
return false;
}
const file = files[0];
if (file.size > 1024 * 1024) {
alert("파일이 너무 큽니다!");
return false;
}
if (file.type === "") {
alert("폴더를 업로드할 수 없습니다!");
return false;
}
const reader = new FileReader();
reader.onload = function () {
let generalData: ExportedInfo;
try {
generalData = JSON.parse(unwrap_any<string>(reader.result));
} catch (e) {
alert("올바르지 않은 파일 형식입니다");
return false;
}
if (!("objType" in generalData)) {
alert("파일 형식을 확인할 수 없습니다");
return false;
}
if (generalData.objType == "battle") {
importBattleInfo(generalData.data);
return true; 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;
} }
const importGeneralInfoByFile = function (files: FileList, $card: JQuery<HTMLElement>) { return true;
if ($card === undefined) { };
$card = addDefender();
} const extendGeneralInfoForDB = function (generalData: GeneralInfo) {
const dbVal = {
if (files === null) { nation: generalData.no <= 1 ? 1 : 2,
alert('파일 에러!'); city: generalData.no <= 1 ? 1 : 3,
return false; turntime: "2018-08-26 12:00",
} special: window.defaultSpecialDomestic,
leadership_exp: 0,
if (files.length < 1) { strength_exp: 0,
alert("파일 에러!"); intel_exp: 0,
return false;
} gold: 10000,
dedication: 0,
const file = files[0];
if (file.size > 1024 * 1024) { recent_war: "2018-08-26 12:00",
alert('파일이 너무 큽니다!'); experience: Math.pow(generalData.explevel, 2),
return false; };
}
if (file.type === '') { return $.extend({}, generalData, dbVal);
alert('폴더를 업로드할 수 없습니다!'); };
return false;
} const getGeneralFrame = function ($btn: JQuery<HTMLElement>) {
const $card = $btn.closest(".general_form");
const reader = new FileReader(); return $card;
reader.onload = function () { };
let generalData: ExportedInfo;
try { const getGeneralDetail = function ($btn: JQuery<HTMLElement>) {
generalData = JSON.parse(unwrap_any<string>(reader.result)); const $card = getGeneralFrame($btn);
} catch (e) { const $general = $card.find(".general_detail");
alert('올바르지 않은 파일 형식입니다'); return $general;
return false; };
}
const getGeneralNo = function ($btn: JQuery<HTMLElement>) {
if (!('objType' in generalData)) { return parseInt(getGeneralFrame($btn).data("general_no"));
alert('파일 형식을 확인할 수 없습니다'); };
return false;
} const setGeneralNo = function ($btn: JQuery<HTMLElement>, value: number) {
if (value == 1) {
if (generalData.objType == 'battle') { //1번은 무조건 공격자임
importBattleInfo(generalData.data); return false;
return true; }
} if (value in defenderNoList) {
if (generalData.objType != 'general') { return false;
alert('장수 데이터가 아닙니다'); }
return false; const $card = getGeneralFrame($btn);
} $card.data("general_no", value);
defenderNoList[value] = $card;
$card.find('.form_load_general_file').val(''); return true;
};
importGeneralInfo($card, generalData.data);
return true; const generateNewGeneralNo = function () {
}; for (;;) {
const newGeneralNo = Math.floor(Math.random() * (1 << 24)) + 2;
try { if (newGeneralNo in defenderNoList) {
continue;
reader.readAsText(file); }
} catch (e) { return newGeneralNo;
alert('파일을 읽는데 실패했습니다.'); }
return false; };
const deleteGeneralNo = function ($btn: JQuery<HTMLElement>) {
const $card = getGeneralFrame($btn);
$card.removeData("general_no");
const generalNo = getGeneralNo($card);
delete defenderNoList[generalNo];
};
const addDefender = function ($cardAfter?: JQuery<HTMLElement>) {
const $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;
};
const deleteDefender = function ($card: JQuery<HTMLElement>) {
deleteGeneralNo($card);
$card.detach();
};
const copyDefender = function ($card: JQuery<HTMLElement>) {
const $general = getGeneralDetail($card);
const generalData = exportGeneralInfo($general);
const $newObj = addDefender($card);
importGeneralInfo(getGeneralDetail($newObj), generalData);
};
const importBattleInfo = function (battleData: BattleInfo) {
$(".form_load_battle_file").val("");
console.log(battleData);
const $attackerNation = $(".attacker_nation");
const $defenderNation = $(".defender_nation");
const attackerGeneral = battleData.attackerGeneral;
const attackerCity = battleData.attackerCity;
const attackerNation = battleData.attackerNation;
const defenderGenerals = battleData.defenderGenerals;
const defenderCity = battleData.defenderCity;
const defenderNation = battleData.defenderNation;
const seed = battleData.seed;
if (seed) {
$("#seed").val(seed);
}
$("#year").val(battleData.year);
$("#month").val(battleData.month);
$("#repeat_cnt").val(battleData.repeatCnt);
$(".delete-defender").trigger("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").trigger("click");
} else {
$attackerNation.find(".form_is_capital:last").trigger("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").trigger("click");
} else {
$defenderNation.find(".form_is_capital:last").trigger("click");
}
$defenderNation.find(".form_city_level").val(defenderCity.level);
$("#city_def").val(defenderCity.def);
$("#city_wall").val(defenderCity.wall);
$.each(defenderGenerals, function (idx, defenderGeneral) {
const $card = addDefender();
importGeneralInfo($card, defenderGeneral);
});
};
const exportAllData = function (): BattleInfo {
const $attackerNation = $(".attacker_nation");
const $defenderNation = $(".defender_nation");
const attackerGeneral = exportGeneralInfo($(".attacker_form"));
const attackerCity = {
level: parseInt($attackerNation.find(".form_city_level").val() as string),
};
const attackerNation = {
type: unwrap_any<string>($attackerNation.find(".form_nation_type").val()),
tech: parseInt($attackerNation.find(".form_tech").val() as string) * 1000,
level: parseInt($attackerNation.find(".form_nation_level").val() as string),
capital: $attackerNation.find(".form_is_capital:checked").val() == "1" ? 1 : 2,
};
const defenderGenerals = $(".defender_form")
.map(function () {
return exportGeneralInfo($(this));
})
.toArray();
const defenderCity = {
def: parseInt($("#city_def").val() as string),
wall: parseInt($("#city_wall").val() as string),
level: parseInt($defenderNation.find(".form_city_level").val() as string),
};
const defenderNation = {
type: unwrap_any<string>($defenderNation.find(".form_nation_type").val()),
tech: parseInt(unwrap_any<string>($defenderNation.find(".form_tech").val())) * 1000,
level: parseInt(unwrap_any<string>($defenderNation.find(".form_nation_level").val())),
capital: $defenderNation.find(".form_is_capital:checked").val() == "1" ? 3 : 4,
};
const year = parseInt(unwrap_any<string>($("#year").val()));
const month = parseInt(unwrap_any<string>($("#month").val()));
const repeatCnt = parseInt(unwrap_any<string>($("#repeat_cnt").val()));
const seed = unwrap_any<string>($("#seed").val());
return {
attackerGeneral: attackerGeneral,
attackerCity: attackerCity,
attackerNation: attackerNation,
defenderGenerals: defenderGenerals,
defenderCity: defenderCity,
defenderNation: defenderNation,
year: year,
month: month,
repeatCnt: repeatCnt,
seed,
};
};
const extendAllDataForDB = function (allData: BattleInfo): BattleInfo {
const defaultNation = {
nation: 0,
name: "재야",
capital: 0,
level: 0,
gold: 0,
rice: 2000,
type: "None",
tech: 0,
gennum: 200,
};
const defaultCity = {
nation: 0,
supply: 1,
name: "도시",
pop: 500000,
agri: 10000,
comm: 10000,
secu: 10000,
def: 1000,
wall: 1000,
trust: 100,
pop_max: 600000,
agri_max: 12000,
comm_max: 12000,
secu_max: 10000,
def_max: 12000,
wall_max: 12000,
dead: 0,
state: 0,
conflict: "{}",
};
const attackerNation = $.extend({}, defaultNation, allData.attackerNation);
attackerNation.nation = 1;
attackerNation.name = "출병국";
const attackerCity = $.extend({}, defaultCity, allData.attackerCity) as CityBasicInfo;
attackerCity.nation = 1;
attackerCity.city = 1;
const attackerGeneral = extendGeneralInfoForDB(allData.attackerGeneral);
if (2 <= attackerGeneral.officer_level && attackerGeneral.officer_level <= 4) {
attackerGeneral.officer_city = 1;
} else {
attackerGeneral.officer_city = 0;
}
const defenderNation = $.extend({}, defaultNation, allData.defenderNation);
defenderNation.nation = 2;
defenderNation.name = "수비국";
const defenderCity = $.extend({}, defaultCity, allData.defenderCity);
defenderCity.nation = 2;
defenderCity.city = 3;
defenderCity.wall_max = Math.floor((defenderCity.wall / 5) * 6);
defenderCity.def_max = Math.floor((defenderCity.def / 5) * 6);
const defenderGenerals: GeneralInfo[] = [];
$.each(allData.defenderGenerals, function () {
const defenderGeneral = extendGeneralInfoForDB(this);
if (2 <= defenderGeneral.officer_level && defenderGeneral.officer_level <= 4) {
defenderGeneral.officer_city = 3;
} else {
defenderGeneral.officer_city = 0;
}
defenderGenerals.push(defenderGeneral);
});
return $.extend({}, allData, {
attackerGeneral: attackerGeneral,
attackerCity: attackerCity,
attackerNation: attackerNation,
defenderGenerals: defenderGenerals,
defenderCity: defenderCity,
defenderNation: defenderNation,
});
};
const parseSkillCount = function (skills: Record<string, number>) {
const result: string[] = [];
for (const [key, value] of Object.entries(skills)) {
result.push(`${key}(${toPretty(value)}회)`);
}
if (result.length == 0) {
return "-";
}
return result.join(", ");
};
const toPretty = function (number: number) {
if (isInteger(number)) {
number = Math.floor(number);
} else {
number = parseFloat(number.toFixed(2));
}
return numberWithCommas(number);
};
const showBattleResult = function (result: BattleResult) {
$("#result_datetime").html(result.datetime);
$("#result_warcnt").html(toPretty(result.avgWar));
$("#result_phase").html(toPretty(result.phase));
$("#result_killed").html(toPretty(result.killed));
if (result.minKilled != result.maxKilled) {
$("#result_maxKilled").html(toPretty(result.maxKilled));
$("#result_minKilled").html(toPretty(result.minKilled));
$("#result_varKilled").show();
} else {
$("#result_varKilled").hide();
}
$("#result_dead").html(toPretty(result.dead));
if (result.minDead != result.maxDead) {
$("#result_maxDead").html(toPretty(result.maxDead));
$("#result_minDead").html(toPretty(result.minDead));
$("#result_varDead").show();
} else {
$("#result_varDead").hide();
}
$("#result_attackerRice").html(toPretty(result.attackerRice));
$("#result_defenderRice").html(toPretty(result.defenderRice));
$("#result_attackerSkills").html(parseSkillCount(result.attackerSkills));
$(".result_defenderSkills").detach();
const $summary = $("#battle_result_summary");
for (const [idx, defenderSkills] of Object.entries(result.defendersSkills)) {
console.log(defenderSkills);
const $result = $(`<tr class='result_defenderSkills'><th>수비자${parseInt(idx) + 1} 스킬</th><td></td></tr>`);
$result.find("td").html(parseSkillCount(defenderSkills));
$summary.append($result);
}
$("#generalBattleResultLog").html(result.lastWarLog.generalBattleResultLog);
$("#generalBattleDetailLog").html(result.lastWarLog.generalBattleDetailLog);
};
const beginBattle = function () {
const 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 () {
alert("전투 개시 실패!");
}
);
};
const reorderDefender = function (defenderOrder: number[]) {
for (const generalNo of defenderOrder) {
if (!(generalNo in defenderNoList)) {
//음..?
alert(`${generalNo}이 수비자 리스트에 없습니다. 버그인 듯 합니다.`);
return true; return true;
}
const $defenderObj = defenderNoList[generalNo];
$defenderObj.detach();
$defenderColumn.append($defenderObj);
} }
};
const extendGeneralInfoForDB = function (generalData: GeneralInfo) { const requestReorderDefender = function () {
const data = extendAllDataForDB(exportAllData());
const dbVal = { console.log(data);
nation: (generalData.no) <= 1 ? 1 : 2, $.ajax({
city: (generalData.no) <= 1 ? 1 : 3, type: "post",
turntime: '2018-08-26 12:00', url: "j_simulate_battle.php",
special: window.defaultSpecialDomestic, dataType: "json",
leadership_exp: 0, data: {
strength_exp: 0, action: "reorder",
intel_exp: 0, query: JSON.stringify(data),
},
gold: 10000, }).then(
function (result) {
dedication: 0, console.log(result);
if (!result.result) {
recent_war: '2018-08-26 12:00', alert(result.reason);
experience: Math.pow(generalData.explevel, 2), return;
};
return $.extend({}, generalData, dbVal);
}
const getGeneralFrame = function ($btn: JQuery<HTMLElement>) {
const $card = $btn.closest('.general_form');
return $card;
}
const getGeneralDetail = function ($btn: JQuery<HTMLElement>) {
const $card = getGeneralFrame($btn);
const $general = $card.find('.general_detail');
return $general;
}
const getGeneralNo = function ($btn: JQuery<HTMLElement>) {
return parseInt(getGeneralFrame($btn).data('general_no'));
}
const setGeneralNo = function ($btn: JQuery<HTMLElement>, value: number) {
if (value == 1) {
//1번은 무조건 공격자임
return false;
} }
if (value in defenderNoList) { reorderDefender(result.order);
return false; },
} function () {
const $card = getGeneralFrame($btn); alert("재정렬 실패!");
$card.data('general_no', value); }
defenderNoList[value] = $card; );
return true; };
}
const generateNewGeneralNo = function () { let initGeneralList = false;
for (; ;) {
const newGeneralNo = Math.floor(Math.random() * (1 << 24)) + 2;
if (newGeneralNo in defenderNoList) {
continue;
}
return newGeneralNo;
}
}
const deleteGeneralNo = function ($btn: JQuery<HTMLElement>) { $("#importFromDB").on("click", function () {
const $card = getGeneralFrame($btn); const generalID = $("#modalSelector").val();
$card.removeData('general_no'); console.log(generalID);
const generalNo = getGeneralNo($card);
delete defenderNoList[generalNo];
}
const addDefender = function ($cardAfter?: JQuery<HTMLElement>) { $.post({
const $newCard = $('<div class="card mb-2 defender_form general_form"></div>'); url: "j_export_simulator_object.php",
dataType: "json",
data: {
destGeneralID: generalID,
},
}).then(function (data) {
if (!data.result) {
alert(data.reason);
return false;
}
if ($cardAfter === undefined) { const $modal = $("#importModal");
$defenderColumn.append($newCard); const $card = $modal.data("target");
} else { importGeneralInfo($card, data.general);
$cardAfter.after($newCard);
}
$newCard.append($defenderHeaderForm.clone(true, true)); if (modalImport) {
$newCard.append($generalForm.clone(true, true)); modalImport.hide();
}
}, errUnknown);
});
//$newGeneral = getGeneralDetail($newCard); unwrap(document.querySelector("#importModal")).addEventListener("show.bs.modal", function () {
setGeneralNo($newCard, generateNewGeneralNo()); if (!initGeneralList) {
const $list = $("#modalSelector");
return $newCard; const addNation = function (generalList: GeneralInfo[], nationName: string, color: string) {
} generalList.sort(function (lhs, rhs) {
if (lhs.npc != rhs.npc) {
const deleteDefender = function ($card: JQuery<HTMLElement>) { return (lhs.npc ?? 0) - (rhs.npc ?? 0);
deleteGeneralNo($card); }
$card.detach(); if (lhs.name < rhs.name) {
} return -1;
}
const copyDefender = function ($card: JQuery<HTMLElement>) { if (lhs.name > rhs.name) {
const $general = getGeneralDetail($card); return 1;
}
const generalData = exportGeneralInfo($general); return 0;
const $newObj = addDefender($card);
importGeneralInfo(getGeneralDetail($newObj), generalData);
}
const importBattleInfo = function (battleData: BattleInfo) {
$('.form_load_battle_file').val('');
console.log(battleData);
const $attackerNation = $('.attacker_nation');
const $defenderNation = $('.defender_nation');
const attackerGeneral = battleData.attackerGeneral;
const attackerCity = battleData.attackerCity;
const attackerNation = battleData.attackerNation;
const defenderGenerals = battleData.defenderGenerals;
const defenderCity = battleData.defenderCity;
const defenderNation = battleData.defenderNation;
const seed = battleData.seed;
if(seed){
$('#seed').val(seed);
}
$('#year').val(battleData.year);
$('#month').val(battleData.month);
$('#repeat_cnt').val(battleData.repeatCnt);
$('.delete-defender').trigger('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').trigger('click');
} else {
$attackerNation.find('.form_is_capital:last').trigger('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').trigger('click');
} else {
$defenderNation.find('.form_is_capital:last').trigger('click');
}
$defenderNation.find('.form_city_level').val(defenderCity.level);
$('#city_def').val(defenderCity.def);
$('#city_wall').val(defenderCity.wall);
$.each(defenderGenerals, function (idx, defenderGeneral) {
const $card = addDefender();
importGeneralInfo($card, defenderGeneral);
}); });
} const $optGroup = $(`<optgroup label="${nationName}"></optgroup>`);
$optGroup.css("background-color", color);
$optGroup.css("color", isBrightColor(color) ? "black" : "white");
const exportAllData = function (): BattleInfo { for (const general of generalList) {
const $attackerNation = $('.attacker_nation'); const $item = $(`<option value="${general.no}">${general.name}</option>`);
const $defenderNation = $('.defender_nation'); if (general.npc) {
$item.css("color", unwrap(getNPCColor(general.npc)));
const attackerGeneral = exportGeneralInfo($('.attacker_form')); } else {
$item.css("color", "white");
const attackerCity = { }
level: parseInt($attackerNation.find('.form_city_level').val() as string), $item.css("background-color", "black");
}; $optGroup.append($item);
}
const attackerNation = { $list.append($optGroup);
type: unwrap_any<string>($attackerNation.find('.form_nation_type').val()), };
tech: parseInt($attackerNation.find('.form_tech').val() as string) * 1000, $.post({
level: parseInt($attackerNation.find('.form_nation_level').val() as string), url: "j_get_basic_general_list.php",
capital: $attackerNation.find('.form_is_capital:checked').val() == '1' ? 1 : 2, dataType: "json",
data: {
req: 2,
},
}).then(function (data: BasicGeneralListResponse | InvalidResponse) {
if (!data.result) {
alert(data.reason);
if (modalImport) {
modalImport.hide();
}
return false;
} }
const defenderGenerals = $('.defender_form').map(function () { const nations = data.nation;
return exportGeneralInfo($(this)); const myNationID = data.nationID;
}).toArray();
const defenderCity = { $list.empty();
def: parseInt($('#city_def').val() as string), //자국 먼저
wall: parseInt($('#city_wall').val() as string),
level: parseInt($defenderNation.find('.form_city_level').val() as string),
};
const defenderNation = { if (0 in data.list) {
type: unwrap_any<string>($defenderNation.find('.form_nation_type').val()), nations[0] = {
tech: parseInt(unwrap_any<string>($defenderNation.find('.form_tech').val())) * 1000,
level: parseInt(unwrap_any<string>($defenderNation.find('.form_nation_level').val())),
capital: $defenderNation.find('.form_is_capital:checked').val() == '1' ? 3 : 4,
}
const year = parseInt(unwrap_any<string>($('#year').val()));
const month = parseInt(unwrap_any<string>($('#month').val()));
const repeatCnt = parseInt(unwrap_any<string>($('#repeat_cnt').val()));
const seed = unwrap_any<string>($('#seed').val());
return {
attackerGeneral: attackerGeneral,
attackerCity: attackerCity,
attackerNation: attackerNation,
defenderGenerals: defenderGenerals,
defenderCity: defenderCity,
defenderNation: defenderNation,
year: year,
month: month,
repeatCnt: repeatCnt,
seed,
};
}
const extendAllDataForDB = function (allData: BattleInfo): BattleInfo {
const defaultNation = {
nation: 0, nation: 0,
name: '재야', name: "재야",
capital: 0, color: "#000000",
level: 0, };
gold: 0,
rice: 2000,
type: 'None',
tech: 0,
gennum: 200,
};
const defaultCity = {
nation: 0,
supply: 1,
name: '도시',
pop: 500000,
agri: 10000,
comm: 10000,
secu: 10000,
def: 1000,
wall: 1000,
trust: 100,
pop_max: 600000,
agri_max: 12000,
comm_max: 12000,
secu_max: 10000,
def_max: 12000,
wall_max: 12000,
dead: 0,
state: 0,
conflict: '{}',
};
const attackerNation = $.extend({}, defaultNation, allData.attackerNation);
attackerNation.nation = 1;
attackerNation.name = '출병국';
const attackerCity = $.extend({}, defaultCity, allData.attackerCity) as CityBasicInfo;
attackerCity.nation = 1;
attackerCity.city = 1;
const attackerGeneral = extendGeneralInfoForDB(allData.attackerGeneral);
if (2 <= attackerGeneral.officer_level && attackerGeneral.officer_level <= 4) {
attackerGeneral.officer_city = 1;
} else {
attackerGeneral.officer_city = 0;
} }
const defenderNation = $.extend({}, defaultNation, allData.defenderNation); addNation(
defenderNation.nation = 2; combineArray(data.list[myNationID], data.column) as GeneralInfo[],
defenderNation.name = '수비국'; nations[myNationID].name,
nations[myNationID].color
);
const defenderCity = $.extend({}, defaultCity, allData.defenderCity); for (const nationID of Object.keys(data.list)) {
defenderCity.nation = 2; if (parseInt(nationID) == myNationID) {
defenderCity.city = 3; continue;
defenderCity.wall_max = Math.floor(defenderCity.wall / 5 * 6); }
defenderCity.def_max = Math.floor(defenderCity.def / 5 * 6); addNation(
combineArray(data.list[nationID], data.column) as GeneralInfo[],
const defenderGenerals: GeneralInfo[] = []; nations[nationID].name,
$.each(allData.defenderGenerals, function () { nations[nationID].color
const defenderGeneral = extendGeneralInfoForDB(this); );
if (2 <= defenderGeneral.officer_level && defenderGeneral.officer_level <= 4) { }
defenderGeneral.officer_city = 3; initGeneralList = true;
} else { }, errUnknown);
defenderGeneral.officer_city = 0;
}
defenderGenerals.push(defenderGeneral);
});
return $.extend({}, allData, {
attackerGeneral: attackerGeneral,
attackerCity: attackerCity,
attackerNation: attackerNation,
defenderGenerals: defenderGenerals,
defenderCity: defenderCity,
defenderNation: defenderNation,
});
} }
});
const parseSkillCount = function (skills: Record<string, number>) { initBasicEvent();
const result: string[] = []; $attackerCard.append($generalForm.clone(true, true));
for (const [key, value] of Object.entries(skills)) { addDefender();
result.push(`${key}(${toPretty(value)}회)`);
}
if (result.length == 0) { $(".btn-begin_battle").on("click", function () {
return '-'; beginBattle();
} });
return result.join(', ');
}
const toPretty = function (number: number) { $(".btn-reorder_defender").on("click", function () {
if (isInteger(number)) { requestReorderDefender();
number = Math.floor(number); });
} else {
number = parseFloat(number.toFixed(2));
}
return numberWithCommas(number);
}
const showBattleResult = function (result: BattleResult) {
$('#result_datetime').html(result.datetime);
$('#result_warcnt').html(toPretty(result.avgWar));
$('#result_phase').html(toPretty(result.phase));
$('#result_killed').html(toPretty(result.killed));
if (result.minKilled != result.maxKilled) {
$('#result_maxKilled').html(toPretty(result.maxKilled));
$('#result_minKilled').html(toPretty(result.minKilled));
$('#result_varKilled').show();
} else {
$('#result_varKilled').hide();
}
$('#result_dead').html(toPretty(result.dead));
if (result.minDead != result.maxDead) {
$('#result_maxDead').html(toPretty(result.maxDead));
$('#result_minDead').html(toPretty(result.minDead));
$('#result_varDead').show();
} else {
$('#result_varDead').hide();
}
$('#result_attackerRice').html(toPretty(result.attackerRice));
$('#result_defenderRice').html(toPretty(result.defenderRice));
$('#result_attackerSkills').html(parseSkillCount(result.attackerSkills));
$('.result_defenderSkills').detach();
const $summary = $('#battle_result_summary');
for (const [idx, defenderSkills] of Object.entries(result.defendersSkills)) {
console.log(defenderSkills);
const $result = $(`<tr class='result_defenderSkills'><th>수비자${parseInt(idx) + 1} 스킬</th><td></td></tr>`);
$result.find('td').html(parseSkillCount(defenderSkills));
$summary.append($result);
}
$('#generalBattleResultLog').html(result.lastWarLog.generalBattleResultLog);
$('#generalBattleDetailLog').html(result.lastWarLog.generalBattleDetailLog);
}
const beginBattle = function () {
const 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 () {
alert('전투 개시 실패!');
});
}
const reorderDefender = function (defenderOrder: number[]) {
for (const generalNo of defenderOrder) {
if (!(generalNo in defenderNoList)) {
//음..?
alert(`${generalNo}이 수비자 리스트에 없습니다. 버그인 듯 합니다.`);
return true;
}
const $defenderObj = defenderNoList[generalNo];
$defenderObj.detach();
$defenderColumn.append($defenderObj);
}
}
const requestReorderDefender = function () {
const 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 () {
alert('재정렬 실패!');
});
}
let initGeneralList = false;
$('#importFromDB').on('click', function () {
const generalID = $('#modalSelector').val();
console.log(generalID);
$.post({
url: 'j_export_simulator_object.php',
dataType: 'json',
data: {
destGeneralID: generalID
}
}).then(function (data) {
if (!data.result) {
alert(data.reason);
return false;
}
const $modal = $('#importModal');
const $card = $modal.data('target');
importGeneralInfo($card, data.general);
if(modalImport){
modalImport.hide();
}
}, errUnknown);
});
unwrap(document.querySelector('#importModal')).addEventListener('show.bs.modal', function () {
if (!initGeneralList) {
const $list = $('#modalSelector');
const addNation = function (generalList: GeneralInfo[], nationName: string, color: string) {
generalList.sort(function (lhs, rhs) {
if (lhs.npc != rhs.npc) {
return (lhs.npc ?? 0) - (rhs.npc ?? 0);
}
if (lhs.name < rhs.name) {
return -1;
}
if (lhs.name > rhs.name) {
return 1;
}
return 0;
})
const $optGroup = $(`<optgroup label="${nationName}"></optgroup>`);
$optGroup.css('background-color', color);
$optGroup.css('color', isBrightColor(color) ? 'black' : 'white');
for (const general of generalList) {
const $item = $(`<option value="${general.no}">${general.name}</option>`);
if (general.npc) {
$item.css('color', unwrap(getNPCColor(general.npc)));
} else {
$item.css('color', 'white');
}
$item.css('background-color', 'black');
$optGroup.append($item);
}
$list.append($optGroup);
}
$.post({
url: 'j_get_basic_general_list.php',
dataType: 'json',
data: {
req: 2,
}
}).then(function (data: BasicGeneralListResponse | InvalidResponse) {
if (!data.result) {
alert(data.reason);
if(modalImport){
modalImport.hide();
}
return false;
}
const nations = data.nation;
const myNationID = data.nationID;
$list.empty();
//자국 먼저
if (0 in data.list) {
nations[0] = {
nation: 0,
name: '재야',
color: '#000000'
};
}
addNation(combineArray(data.list[myNationID], data.column) as GeneralInfo[], nations[myNationID].name, nations[myNationID].color);
for (const nationID of Object.keys(data.list)) {
if (parseInt(nationID) == myNationID) {
continue;
}
addNation(combineArray(data.list[nationID], data.column) as GeneralInfo[], nations[nationID].name, nations[nationID].color);
}
initGeneralList = true;
}, errUnknown);
}
});
initBasicEvent();
$attackerCard.append($generalForm.clone(true, true));
addDefender();
$('.btn-begin_battle').on('click', function () {
beginBattle();
});
$('.btn-reorder_defender').on('click', function () {
requestReorderDefender();
})
}); });