1109 lines
32 KiB
TypeScript
1109 lines
32 KiB
TypeScript
import $ from "jquery";
|
|
import "bootstrap";
|
|
import download from "downloadjs";
|
|
import { unwrap } from "@util/unwrap";
|
|
import { isInteger } from "lodash-es";
|
|
import { errUnknown } from "@/common_legacy";
|
|
import { getNPCColor } from "./utilGame";
|
|
import { combineArray } from "@util/combineArray";
|
|
import { isBrightColor } from "@util/isBrightColor";
|
|
import { numberWithCommas } from "@util/numberWithCommas";
|
|
import { unwrap_any } from "@util/unwrap_any";
|
|
import type { BasicGeneralListResponse, InvalidResponse } from "@/defs";
|
|
import { formatTime } from "@util/formatTime";
|
|
import { Modal } from "bootstrap";
|
|
|
|
type CityAttackerInfo = {
|
|
level: number;
|
|
};
|
|
|
|
type CityBasicInfo = {
|
|
nation?: number;
|
|
level: number;
|
|
def: number;
|
|
wall: number;
|
|
city?: number;
|
|
};
|
|
|
|
type NationBasicInfo = {
|
|
level: number;
|
|
type: string;
|
|
tech: number;
|
|
capital: number;
|
|
};
|
|
|
|
type InheritBuff = {
|
|
warAvoidRatio: number;
|
|
warCriticalRatio: number;
|
|
warMagicTrialProb: number;
|
|
warAvoidRatioOppose: number;
|
|
warCriticalRatioOppose: number;
|
|
warMagicTrialProbOppose: number;
|
|
};
|
|
|
|
type GeneralInfo = {
|
|
no: number;
|
|
npc?: number;
|
|
name: string;
|
|
officer_level: number;
|
|
explevel: number;
|
|
|
|
leadership: number;
|
|
horse: string;
|
|
strength: number;
|
|
weapon: string;
|
|
intel: number;
|
|
book: string;
|
|
item: string;
|
|
|
|
injury: number;
|
|
|
|
rice: number;
|
|
|
|
personal: string;
|
|
special2: string;
|
|
|
|
crew: number;
|
|
crewtype: number;
|
|
atmos: number;
|
|
train: number;
|
|
|
|
dex1: number;
|
|
dex2: number;
|
|
dex3: number;
|
|
dex4: number;
|
|
dex5: number;
|
|
|
|
defence_train: number;
|
|
|
|
warnum: number;
|
|
killnum: number;
|
|
killcrew: number;
|
|
|
|
officer_city?: number;
|
|
|
|
inheritBuff?: InheritBuff;
|
|
};
|
|
|
|
type BattleInfo = {
|
|
attackerGeneral: GeneralInfo;
|
|
attackerCity: CityAttackerInfo | CityBasicInfo;
|
|
attackerNation: NationBasicInfo;
|
|
defenderGenerals: GeneralInfo[];
|
|
defenderCity: CityBasicInfo;
|
|
defenderNation: NationBasicInfo;
|
|
year: number;
|
|
month: number;
|
|
repeatCnt: number;
|
|
seed?: string;
|
|
};
|
|
|
|
type ExportedGeneralInfo = {
|
|
objType: "general";
|
|
data: GeneralInfo;
|
|
};
|
|
|
|
type ExportedBattleInfo = {
|
|
objType: "battle";
|
|
data: BattleInfo;
|
|
};
|
|
type ExportedInfo = ExportedGeneralInfo | ExportedBattleInfo;
|
|
|
|
type BattleResult = {
|
|
result: true;
|
|
datetime: string;
|
|
lastWarLog: {
|
|
generalBattleResultLog: string;
|
|
generalBattleDetailLog: string;
|
|
};
|
|
avgWar: number;
|
|
phase: number;
|
|
killed: number;
|
|
maxKilled: number;
|
|
minKilled: number;
|
|
dead: number;
|
|
maxDead: number;
|
|
minDead: number;
|
|
attackerRice: number;
|
|
defenderRice: number;
|
|
attackerSkills: Record<string, number>;
|
|
defendersSkills: Record<string, number>[];
|
|
};
|
|
|
|
declare global {
|
|
interface Window {
|
|
nation?: NationBasicInfo;
|
|
city?: CityBasicInfo;
|
|
defaultSpecialDomestic: string;
|
|
}
|
|
}
|
|
|
|
let modalImport: Modal | undefined = undefined;
|
|
|
|
$(function ($) {
|
|
const $generalForm = $(".form_sample .general_detail");
|
|
const $defenderHeaderForm = $(".form_sample .card-header");
|
|
const $defenderColumn = $(".defender-column");
|
|
|
|
const defenderNoList: Record<number, JQuery<HTMLElement>> = {};
|
|
|
|
const $attackerCard = $(".attacker_form");
|
|
|
|
const initBasicEvent = function () {
|
|
if (window.nation && window.city) {
|
|
$(".form_city_level").val(window.city.level);
|
|
$(".form_def").val(window.city.def);
|
|
$(".form_wall").val(window.city.wall);
|
|
$(".form_nation_type").val(window.nation.type);
|
|
$(".form_nation_level").val(window.nation.level);
|
|
$(".form_tech").val(window.nation.tech / 1000);
|
|
if (window.nation.capital == window.city.city) {
|
|
$(".attacker_nation .form_is_capital:first").trigger("click");
|
|
$(".defender_nation .form_is_capital:first").trigger("click");
|
|
} else {
|
|
$(".attacker_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) {
|
|
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);
|
|
}
|
|
|
|
if (!setGeneralNo($general, data.no)) {
|
|
setGeneralNo($general, generateNewGeneralNo());
|
|
}
|
|
};
|
|
|
|
const exportGeneralInfo = function ($general: JQuery<HTMLElement>): GeneralInfo {
|
|
const getInt = function (query: string): number {
|
|
return parseInt(unwrap_any<string>($general.find(query).val()));
|
|
};
|
|
|
|
const getVal = function (query: string): string {
|
|
return unwrap_any<string>($general.find(query).val());
|
|
};
|
|
|
|
return {
|
|
no: getGeneralNo($general),
|
|
name: getVal(".form_general_name"),
|
|
officer_level: getInt(".form_officer_level"),
|
|
explevel: getInt(".form_exp_level"),
|
|
|
|
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"),
|
|
|
|
injury: getInt(".form_injury"),
|
|
|
|
rice: getInt(".form_rice"),
|
|
|
|
personal: getVal(".form_general_character"),
|
|
special2: getVal(".form_general_special_war"),
|
|
|
|
crew: getInt(".form_crew"),
|
|
crewtype: getInt(".form_crewtype"),
|
|
atmos: getInt(".form_atmos"),
|
|
train: getInt(".form_train"),
|
|
|
|
dex1: getInt(".form_dex1"),
|
|
dex2: getInt(".form_dex2"),
|
|
dex3: getInt(".form_dex3"),
|
|
dex4: getInt(".form_dex4"),
|
|
dex5: getInt(".form_dex5"),
|
|
|
|
defence_train: getInt(".form_defence_train"),
|
|
|
|
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;
|
|
}
|
|
|
|
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 battleData: ExportedInfo;
|
|
try {
|
|
battleData = JSON.parse(unwrap_any<string>(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;
|
|
};
|
|
|
|
const importGeneralInfoByFile = function (files: FileList, $card: JQuery<HTMLElement>) {
|
|
if ($card === undefined) {
|
|
$card = addDefender();
|
|
}
|
|
|
|
if (files === null) {
|
|
alert("파일 에러!");
|
|
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;
|
|
}
|
|
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;
|
|
};
|
|
|
|
const extendGeneralInfoForDB = function (generalData: GeneralInfo) {
|
|
const dbVal = {
|
|
nation: generalData.no <= 1 ? 1 : 2,
|
|
city: generalData.no <= 1 ? 1 : 3,
|
|
turntime: "2018-08-26 12:00",
|
|
special: window.defaultSpecialDomestic,
|
|
leadership_exp: 0,
|
|
strength_exp: 0,
|
|
intel_exp: 0,
|
|
|
|
gold: 10000,
|
|
|
|
dedication: 0,
|
|
|
|
recent_war: "2018-08-26 12:00",
|
|
experience: Math.pow(generalData.explevel, 2),
|
|
};
|
|
|
|
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) {
|
|
return false;
|
|
}
|
|
const $card = getGeneralFrame($btn);
|
|
$card.data("general_no", value);
|
|
defenderNoList[value] = $card;
|
|
return true;
|
|
};
|
|
|
|
const generateNewGeneralNo = function () {
|
|
for (;;) {
|
|
const newGeneralNo = Math.floor(Math.random() * (1 << 24)) + 2;
|
|
if (newGeneralNo in defenderNoList) {
|
|
continue;
|
|
}
|
|
return newGeneralNo;
|
|
}
|
|
};
|
|
|
|
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;
|
|
}
|
|
|
|
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();
|
|
});
|
|
});
|