import axios from 'axios'; import { errUnknown } from '@/common_legacy'; import { getIconPath } from "@util/getIconPath"; import { TemplateEngine } from "@util/TemplateEngine"; import { getNPCColor } from "@/utilGame"; import type { GeneralListResponse, InvalidResponse, PublicGeneralItem } from '@/defs'; import { convertFormData } from '@util/convertFormData'; import { unwrap_any } from '@util/unwrap_any'; import { setAxiosXMLHttpRequest } from '@util/setAxiosXMLHttpRequest'; import { Tooltip } from 'bootstrap'; import { trim } from 'lodash-es'; import { SammoAPI } from './SammoAPI'; import { unwrap } from './util/unwrap'; setAxiosXMLHttpRequest(); declare const specialInfo: Record; declare const characterInfo: Record; declare global { interface Window { generalList: NPCPickPrintable[], } } type NPCPick = { no: number, name: string, leadership: number, strength: number, intel: number, nation: string, imgsvr: 0 | 1, picture: string, personal: string, special: string, special2: string, iconPath?: string, specialText?: string, special2Text?: string, personalText?: string, } type NPCPickPrintableR = PublicGeneralItem & { reserved: number, userCSS?: string, nameAux?: string, total?: number, iconPath?: string, specialDomesticWithTooltip?: string, specialWarWithTooltip?: string, personalWithTooltip?: string, } type NPCPickPrintable = NPCPickPrintableR & { userCSS: string, nameAux: string, total: number, iconPath: string, specialDomesticWithTooltip: string, specialWarWithTooltip: string, personalWithTooltip: string, } type NPCToken = { result: true, pick: Record, pickMoreFrom: string, pickMoreSeconds: number, validUntil: string, } const templateGeneralCard = '
\

<%name%>

\

\

<%leadership%> / <%strength%> / <%intel%>
\ <%nation%>
\ <%personalText%>
\ <%specialText%> / <%special2Text%>

\ \ \
'; const templateSpecial = '<%text%>\ \ <%info%>\ \ \ '; const templateGeneralRow = '\ \ <%name%><%nameAux%>\ <%age%>세\ <%personalWithTooltip%>\ <%specialDomesticWithTooltip%> / <%specialWarWithTooltip%>\ Lv <%explevel%>\ <%nation%>\ <%experienceStr%>\ <%dedicationStr%>\ <%officerLevelStr%>\ <%total%>\ <%leadership%>\ <%strength%>\ <%intel%>\ <%killturn%>\ '; async function pickGeneral(this: HTMLElement, e: JQuery.Event) { e.preventDefault(); const $btn = $(this); if (!confirm(`빙의할까요? : ${$btn.data('name')}`)) { return; } let result: InvalidResponse; try { const response = await axios({ url: 'j_select_npc.php', responseType: 'json', method: 'post', data: convertFormData({ pick: unwrap_any($btn.val()), }) }); result = response.data; } catch (e) { alert(`알 수 없는 에러: ${e}`); return; } if (!result.result) { alert(result.reason); location.reload(); return; } alert('빙의에 성공했습니다.'); location.href = './'; } function updateOutdateTimer() { const $validUntilText = $('#valid_until_text'); const now = Date.now(); const validUntil = $validUntilText.data('until'); if (validUntil <= 0) { return; } else if (validUntil < now) { $validUntilText.data('until', 0); $('#valid_until').hide(); $('#outdate_token').show(); return; } else if (validUntil - now <= 30000) { const remainColor = 255 * (validUntil - now) / 30000; $validUntilText.css('color', `rgb(255, ${remainColor}, ${remainColor})`); } setTimeout(updateOutdateTimer, 1000); } function updatePickMoreTimer() { const $btn = $('#btn_pick_more'); const now = Date.now(); const remain = ($btn.data('available') - now) / 1000; if (remain <= 0) { $btn.prop('disabled', false) $btn.html('다른 장수 보기'); return; } $btn.html(`다른 장수 보기(${Math.ceil(remain)}초)`); setTimeout(updatePickMoreTimer, 250); } function printGenerals(value: NPCToken) { $('.card_holder').empty(); $('#valid_until').show(); $('#valid_until_text').html(value.validUntil).data('until', (new Date(value.validUntil)).getTime()).css('color', 'white'); $('#outdate_token').hide(); const time = Date.now() + value.pickMoreSeconds * 1000; $('#btn_pick_more').data('available', time).prop('disabled', true); const pick = $.map(value.pick, function (value) { return value; }); pick.sort(function (lhs, rhs) { const lsum = lhs.leadership + lhs.strength + lhs.intel; const rsum = rhs.leadership + rhs.strength + rhs.intel; return lsum - rsum; }); $.each(pick, function (idx, cardData: NPCPick) { cardData.iconPath = getIconPath(cardData.imgsvr, cardData.picture); if (cardData.special in specialInfo) { cardData.specialText = TemplateEngine(templateSpecial, { text: cardData.special, info: specialInfo[cardData.special] }); } else { cardData.specialText = cardData.special; } if (cardData.special2 in specialInfo) { cardData.special2Text = TemplateEngine(templateSpecial, { text: cardData.special2, info: specialInfo[cardData.special2] }); } else { cardData.special2Text = cardData.special2; } if (cardData.personal in characterInfo) { cardData.personalText = TemplateEngine(templateSpecial, { text: cardData.personal, info: characterInfo[cardData.personal] }); } else { cardData.personalText = cardData.personal; } const $card = $(TemplateEngine(templateGeneralCard, cardData)); $('.card_holder').append($card); $card.find('.select_btn').on('click', pickGeneral); $card.find('.obj_tooltip').each(function(){ new Tooltip(this, { title: function () { return trim(this.querySelector('.tooltiptext')?.innerHTML); }, html: true }); }); }); updatePickMoreTimer(); updateOutdateTimer(); } function printGeneralList(value: GeneralListResponse) { console.log(value); const tokenList = unwrap(value.token); const generalList: NPCPickPrintable[] = value.list.map((rawGeneral) => { const general: NPCPickPrintableR = { no: rawGeneral[0], picture: rawGeneral[1], imgsvr: rawGeneral[2], npc: rawGeneral[3], age: rawGeneral[4], nation: rawGeneral[5], specialDomestic: rawGeneral[6], specialWar: rawGeneral[7], personal: rawGeneral[8], name: rawGeneral[9], ownerName: rawGeneral[10], injury: rawGeneral[11], leadership: rawGeneral[12], lbonus: rawGeneral[13], strength: rawGeneral[14], intel: rawGeneral[15], explevel: rawGeneral[16], experienceStr: rawGeneral[17], dedicationStr: rawGeneral[18], officerLevelStr: rawGeneral[19], killturn: rawGeneral[20], refreshScoreTotal: rawGeneral[21], reserved: 0 }; if (general.npc < 2) { general.reserved = 2; } if (general.no in tokenList) { general.reserved = 1; } general.userCSS = ""; general.nameAux = ""; if (general.reserved == 1) { general.userCSS = 'color:violet'; } else if (general.npc > 0) { general.userCSS = `color:${getNPCColor(general.npc)}`; } if (general.ownerName) { general.nameAux += `
(${general.ownerName})`; } if (general.reserved == 1) { general.nameAux += `
(${tokenList[general.no]}회)`; } general.total = general.leadership + general.strength + general.intel; general.iconPath = getIconPath(general.imgsvr, general.picture); general.specialDomesticWithTooltip = TemplateEngine(templateSpecial, { text: general.specialDomestic, info: specialInfo[general.specialDomestic] }); general.specialWarWithTooltip = TemplateEngine(templateSpecial, { text: general.specialWar, info: specialInfo[general.specialWar] }); general.personalWithTooltip = TemplateEngine(templateSpecial, { text: general.personal, info: characterInfo[general.personal] }); return general as NPCPickPrintable; }); generalList.sort(function (lhs, rhs) { if (lhs.reserved > rhs.reserved) { return -1; } if (lhs.reserved < rhs.reserved) { return 1; } if (lhs.total != rhs.total) { return rhs.total - lhs.total; } if (lhs.leadership != rhs.leadership) { return rhs.leadership - lhs.total; } if (lhs.name < rhs.name) { return -1; } if (lhs.name > rhs.name) { return 1; } return 0; }); window.generalList = generalList; _printGeneralList(true); } function _printGeneralList(clear?: boolean) { const $generalTable = $('#general_list'); if (clear) { $generalTable.empty(); $generalTable.data('lastIdx', 0); $('#row_print_more').show(); } const generalList = window.generalList; const idxFrom = $generalTable.data('lastIdx'); const idxTo = Math.min(idxFrom + 50, generalList.length); $generalTable.data('lastIdx', idxTo); for (let idx = idxFrom; idx < idxFrom + 50; idx++) { const general = generalList[idx]; $generalTable.append(TemplateEngine(templateGeneralRow, general)); } if (idxTo == generalList.length) { $('#row_print_more').hide(); } $generalTable.find('.obj_tooltip').each(function(){ new Tooltip(this, { title: function () { return trim(this.querySelector('.tooltiptext')?.innerHTML); }, html: true }) }); $('#tb_general_list').show(); } $(function ($) { window.generalList = []; $.post('j_get_select_npc_token.php').then(function (value) { if (!value.result) { alert(value.reason); return; } console.log(value); printGenerals(value); }, errUnknown); $('#btn_pick_more').click(function () { const generals = $('.keep_select:checked').map(function () { return unwrap_any($(this).val()); }).toArray(); 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.reload(); } console.log(result); printGenerals(result); }, errUnknown); }); $('#btn_load_general_list').on('click', async function () { try { const result = await SammoAPI.Global.GeneralListWithToken(); printGeneralList(result); } catch (e) { console.error(e); alert(`실패했습니다: ${e}`); return; } }); $('#btn_print_more').on('click', function () { _printGeneralList(); }) });