「javascript/クエスト情報変換【タブ用】」の編集履歴(バックアップ)一覧に戻る

javascript/クエスト情報変換【タブ用】 - (2021/08/12 (木) 21:39:47) のソース

#js(){{{{{
	<style type="text/css">
	input[name="BOLD"]:checked + input {
		font-weight: bold;
	}
	select {
		padding: 3px 0px;
		vertical-align: bottom;
		margin: 1px;
	}
	input {
		padding: 3px 0px;
		margin: 1px 0px;
	}
	input[type="checkbox"],
	label {
		cursor: pointer;
	}
	textarea {
		box-sizing: border-box;
		width: 100%;
		height: 50px;
		vertical-align: bottom;
		text-align: center;
	}
	.clearbtn,
	.minibtn {
		padding: 0;
		min-width: 1.5em;
		margin: 3px;
	}
	</style>
	<script type="text/javascript">
	
	// テキストノード追加拡張
	$.fn.appendText = function(text) {
		return this.each(function() {
			var textNode = document.createTextNode(text);
			$(this).append(textNode);
		});
	};
	
	var QuestGen = (function () {
	
		const defaults = {
			design: 0,
			max_wave: 9,
			max_phase: 9,
			max_support: 9,
			max_enemyleft: 9,
			max_enemyright: 9,
			bold_color: ["#e6e6fa","#bee0c2","#fddea5"],
			back_color: ["#f5fffa","#f5fffa","#f5fffa"],
			caption_color: ["#17184b","#004d25","#d3381c"],
			class_list: ['剣', '弓', '槍', '騎', '術', '殺', '狂', '盾', '裁', '讐', '月', '分', '獣', '失', '降', '騙','獣','?'],
		};
		
		/**
		* defaultsとインスタンスoptionsのマージ用(settings)
		* Merge two or more objects. Returns a new object.
		* @private
		* @param {Boolean}  deep	 If true, do a deep (or recursive) merge [optional]
		* @param {Object}   objects  The objects to merge together
		* @returns {Object}		  Merged values of defaults and options
		*/
		const extend = function ()  {
	
			let extended = {};
			let deep = false;
			let i = 0;
			let length = arguments.length;
	
			/* Check if a deep merge */
			if (Object["proto"+"type"].toString.call(arguments[0]) === "[object Boolean]") {
				deep = arguments[0];
				i++;
			}
	
			/* Merge the object into the extended object */
			let merge = function (obj) {
				for (let prop in obj) {
					if (Object["proto"+"type"].hasOwnProperty.call(obj, prop)) {
						/* If deep merge and property is an object, merge properties */
						if (deep && Object["proto"+"type"].toString.call(obj[prop]) === "[object Object]") {
							extended[prop] = extend(true, extended[prop], obj[prop]);
						} else {
							extended[prop] = obj[prop];
						}
					}
				}
			};
	
			/* Loop through each object and conduct a merge */
			for (; i < length; i++) {
				let obj = arguments[i];
				merge(obj);
			}
	
			return extended;
		};
		// String.repeat (IE対応)
		const Repeat = function(str, count) {
			var rpt = '';
			for (;;) {
				if ((count & 1) == 1) {
					rpt += str;
				}
				count >>>= 1;
				if (count == 0) {
					break;
				}
				str += str;
			}
			return rpt;
		}
	
		// C#風String.Format
		const Format = function(te, re) {
			if (typeof re != "object")
				re = Array["proto"+"type"].slice.call(arguments, 1);
			return te.replace(/{(\d+)}/g, function(m, c) {
				return (re[c] != null) ? re[c] : ' ';
			});
		};
		
		// 3桁区切り
		const toComma = function(num) {
			if (typeof(num) === 'undefined')
				return '';
			if (typeof(num) === 'string')
				num = parseInt(num);
			if (Number.isNaN(num))
				return '';
			return parseInt(num / 1000) == 0 ? num % 1000 : toComma(parseInt(num / 1000)) + ',' + ('000' + (num % 1000)).slice(-3);
		}
	
		function QuestGen(target, options) {
			this.settings = extend(defaults, options || {});
			this.target = target;
			this.init();
		}
		QuestGen["proto"+"type"] = {
			init: function() {
				this.phase = 1;
				this.tempClsSelect = $('<select>', {'name': 'SVTCLS'}).css('width', '3em').append($.map(this.settings.class_list, function(e) { return $('<option>').text(e); }));
				var self = this;
				this.tempClearBtn = $('<input>', {'type': 'button', 'data-target': 'tr'}).addClass('clearbtn').css('padding', '0').val('消').click(function() {
					let data = $(this).attr('data-target');
					self.clearInput(data ? $(this).parents(data) : $(this).parent());
				});
				this.setDesign(0);
			},
			getBg: function() { return this.settings.back_color[this.settings.design]; },
			getBold: function() { return this.settings.bold_color[this.settings.design]; },
			getCaption: function() { return this.settings.caption_color[this.settings.design]; },
			// テーブル色変更
			setDesign: function(num) {
				this.settings.design = num;
				$('style#design').remove();
				let style = '<style type="text/css" id="design">';
				style += '.phase td { background-color: ' + this.getBg() + '; text-align: center; }';
				style += '.headrow { background-color: '+ this.getCaption() +'!important; color: white; }';
				style += '.subrow { background-color: '+ this.getBold() +'!important; }';
				style += '</style>';
				$('head').append(style);
			},
			// ターゲット以下の入力欄を削除
			clearInput: function(tgt) {
				$('input[type="number"],input[type="text"]', tgt).val('');
				$('input[type="checkbox"]', tgt).prop('checked', false).change();
				$('select', tgt).prop('selectedIndex', 0).change();
			},
			// 入力欄を作成する
			makeTable: function() {
				let table = $('<table>', {'cellspacing': "1", 'border': "0"}).addClass('phase');
				table.append(this.makeHead());
				table.append(this.makeWaves());
				table.append(this.makeSupport());
				table.append(this.makeEnemy(true));
				table.append(this.makeEtc());
				table.appendTo(this.target);
			},
			// クエスト共通部分の作成
			makeHead: function() {
				let thead = $('.template thead').clone(true);
				thead.find('td:eq(0)').prepend(this.tempClearBtn.clone(true).attr('data-target', 'thead'));
				return thead;
			},
			// エネミー欄の作成
			makeEnemy: function(addcontrol) {
				var addcontrol = (addcontrol !== undefined) ? addcontrol : false;
				let tbody = $('<tbody>').addClass('enemydetail');
				var self = this;
				{
					let td = $('<td>', {'colspan': 4, 'class': 'subrow'});
					if (addcontrol) {
						let changeRowFunc = function() {
							let elems = $('.enemydetail', self.target);
							if ($(this).attr('name') == 'ADDROW') {
								$(elems[elems.length-1]).after(self.makeEnemy());
							} else if (elems.length > 1) {
								$(elems[elems.length-1]).remove();
							}
						};
						td.append($('<input>', {'type': 'button', 'name': 'SUBROW'}).addClass('minibtn').css('float', 'left').val('-').click(changeRowFunc));
						td.append($('<input>', {'type': 'button', 'name': 'ADDROW'}).addClass('minibtn').css('float', 'left').val('+').click(changeRowFunc));
					}
					this.tempClearBtn.clone(true).attr('data-target', 'tbody').prop('disabled', $('#clearLock').prop('checked') || false).appendTo(td);
					td.appendText('エネミー《');
					td.appendText('隠').append($('<input>', {'type': 'checkbox', 'name': 'HIDE'}));
					$('<input>', {'type': 'text', 'name': 'NAME'}).css('width', '12em').appendTo(td);
					td.appendText('》(左列行数:');
					let sel = $('<select>', {'name': 'LEFTNUM'}).css('width', '3em')
					.append($.map(Array.apply(null, {length: this.settings.max_enemyleft+1}).map(Function.call, Number), function(e) { return $('<option>').text(e); }))
					.prop('selectedIndex', 0)
					.change(function() {
						let lines = $(this).parents('tbody').children('tr:nth-child(n+2)');
						var num = $(this).val() * self.settings.max_enemyright;
						lines.each(function(i, e) {
							if (num-- > 0)
								$(e).show();
							else
								$(e).hide();
						});
					}).appendTo(td);
					td.appendText(')【0=エネミー欄非表示】');
					tbody.append($('<tr>').append(td));
				}
	
				for (let i = 0; i < this.settings.max_enemyleft; i++) {
					let td = $('<td>', {'colspan': 2, 'rowspan': this.settings.max_enemyright})
					.append($('<input>', {'type': 'text', 'name': 'LEFTTEXT'}).css('width', '12em'))
					.append($('<br>'))
					.appendText('(右列行数');
					
					let rsel = $('<select>', {'name': 'RIGHTNUM'}).css('width', '3em')
					.append($.map(Array.apply(null, {length: this.settings.max_enemyright}).map(Function.call, Number), function(e) { return $('<option>').text(e+1); }))
					.prop('selectedIndex', 0)
					.change(function() {
						let val = $(this).val();
						let cur = $(this).parents('tr');
						for (let n = 0; n < self.settings.max_enemyright; n++) {
							if (n < val) {
								cur.children('td:last-child').show();
							} else {
								cur.children('td:last-child').hide();
							}
							cur = cur.next();
						}
					}).appendTo(td);
					td.appendText(')');
					var tr = $('<tr>').hide().append(td);
					$('<td>', {'colspan': 2}).append($('<textarea>', {'name': 'RIGHTTEXT'})).appendTo(tr);
					tbody.append(tr);
					// 右列の処理(2こめ以降)
					let remain = this.settings.max_enemyright - 1;
					for (let r = 0; r < remain; r++) {
						tr = $('<tr>').hide();
						$('<td>', {'colspan': 2}).append($('<textarea>', {'name': 'RIGHTTEXT'})).hide().appendTo(tr);
						tbody.append(tr);
					}
				}
				return tbody;
			},
			// 備考欄の作成
			makeEtc: function() {
				let tbody = $('<tbody>');
				let td = $('<td>', {'colspan': 4, 'class': 'subrow'})
				.append(this.tempClearBtn.clone(true).attr('data-target', 'tbody'))
				.appendText('備考 (');
				
				$('<input>', {'type': 'checkbox', 'name': 'ETCON'}).change(function() {
					let tarea = $('textarea[name="TEXT"]', $(this).parents('tbody'));
					if ($(this).prop('checked'))
						tarea.show();
					else
						tarea.hide();
				}).appendTo(td);
				td.appendText('表示)');
				tbody.append($('<tr>').append(td));
				td = $('<td>', {'colspan': 4});
				$('<textarea>', {'name': 'TEXT'}).hide().appendTo(td);
				tbody.append($('<tr>').append(td));
				return tbody;
			},
			// 全WAVEの敵デッキの作成
			makeWaves: function(visible_count) {
				var visible_count = (visible_count !== undefined) ? visible_count : 3;
				let tbody = $('<tbody>').addClass('enemydecks');
				// ヘッダー欄
				{
					let tr = $('<tr>');
					let td = $('<td>', {'colspan': 2, 'class': 'subrow'});
					this.tempClearBtn.clone(true).attr('data-target', 'tbody').appendTo(td);
					$('<input>', {'type': 'text', 'name': 'QID'}).css('width', '5em').appendTo(td);
					td.appendText(' 全');
					let sel = $('<select>', {'name': 'WAVECOUNT'}).css('width', '3em');
					for (let i = 0; i < this.settings.max_wave+1; i++) {
						$('<option>').text(i).appendTo(sel);
					}
					sel.prop('selectedIndex', visible_count);
					var self = this;
					sel.change(function() {
						let val = parseInt($(this).val());
						$('.wave', tbody).each(function() {
							if (parseInt($(this).attr('data-wave')) <= val)
								$(this).show();
							else
								$(this).hide();
						});
					});
					sel.appendTo(td);
					td.appendText('【0=Battleなし】');
					tr.append(td);
					td = $('<td>', {'colspan': 2, 'class': 'subrow'});
					td.appendText('クラス構成');
					let ad = $('<label>(手動:<input type="checkbox" name="MANUALDETAIL">)</label>').appendTo(td);
					ad = ad.children('input');
					ad.change(function() {
						$(this).parent().next().prop('disabled', !$(this).prop('checked'));
					});
					$('<input>', {'type': 'text', 'name': 'DECKDETAIL'}).css('width', '15em').prop('disabled', true).appendTo(td);
					tbody.append(tr.append(td));
				}
				let unit = this.makeSvt();
				// 1WAVEのエネミー入力欄の増減
				let changeRowFunc = function() {
					let tr = $(this).parents('tr');
					let tr_end = tr;
					let current_wave = tr.attr('data-wave');
					let count = 0;
					for (let elem = tr; elem.length > 0 && elem.attr('data-wave') == current_wave; elem = elem.next()) {
						tr_end = elem;
						count++;
					}
					if ($(this).attr('name') == 'ADDROW') {
						tr.children('td:eq(0)').attr('rowspan', count+1);
						tr = $('<tr>').attr('data-wave', current_wave).addClass('wave');
						for (let j = 0; j < 3; j++) {
							unit.clone(true).appendTo(tr);
						}
						tr_end.after(tr);
					} else if (tr != tr_end) {
						tr.children('td:eq(0)').attr('rowspan', count-1);
						tr_end.remove();
					}
				};
				for (let i = 0; i < this.settings.max_wave; i++) {
					let tr = $('<tr>').attr('data-wave', i+1).addClass('wave').css('display', i < visible_count ? 'table-row' : 'none');
					$('<td>').text(i+1)
					.append(this.tempClearBtn.clone(true))
					.append($('<br>'))
					.append($('<input>', {'type': 'button', 'name': 'SUBROW'}).addClass('minibtn').val('-').click(changeRowFunc))
					.append($('<input>', {'type': 'button', 'name': 'ADDROW'}).addClass('minibtn').val('+').click(changeRowFunc))
					.appendTo(tr);
					for (let j = 0; j < 3; j++) {
						unit.clone(true).appendTo(tr);
					}
					tbody.append(tr);
				}
				return tbody;
			},
			// ユニット入力欄の生成
			makeSvt: function() {
				let td = $('<td>').addClass('unit');
				td.appendText('隠').append($('<input>', {'type': 'checkbox', 'name': 'HIDE'}));
				//td.appendText('太').append($('<input>', {'type': 'checkbox', 'name': 'BOLD'}));
				$('<input>', {'type': 'text', 'name': 'NAME'}).css('width', '12em').appendTo(td);
				td.appendText('◆');
				let sel = $('<select>',{'name': 'SHIFT'}).css('width', '3em');
				for (let i = 0; i < 5; i++) {
					$('<option>').text(i).appendTo(sel);
				}
				sel.change(function() {
					let shifts = $('div', $(this).parent());
					shifts.hide();
					for (let i = 0; i < $(this).prop('selectedIndex')+1; i++) {
						$(shifts[3-i]).show();
					}
				});
				sel.appendTo(td);
				$('<br>').appendTo(td);
				
				for (let i = 0; i < 5; i++) {
					let div = $('<div>').css('white-space', 'nowrap');
					if (i < 4)
						div.css('display', 'none');
					div.appendText('Lv');
					$('<input>', {'type': 'number', 'name': 'LV', 'min': 0}).css('width', '3em').appendTo(div);
					div.appendText('(');
					this.tempClsSelect.clone(true).appendTo(div);
					$('<span>').text(')'+Repeat(' ', i)+Repeat('◆', 4-i)+'HP').appendTo(div);
					$('<input>', {'type': 'number', 'name': 'HP', 'min': 0}).css('width', '6em').appendTo(div);
					div.appendTo(td);
				}
				return td;
			},
			// サポートNPC欄の作成
			makeSupport: function() {
				let tbody = $('<tbody>').addClass('support');
				let td = $('<td>', {'colspan': 4, 'class': 'subrow'}).text('サポートNPC(計');
				this.tempClearBtn.clone(true).attr('data-target', 'tbody').prependTo(td);
				let sel = $('<select>', {'name': 'SUPNUM'}).css('width', '3em')
				.append($.map(Array.apply(null, {length: this.settings.max_support+1}).map(Function.call, Number), function(e) { return $('<option>').text(e); }))
				.prop('selectedIndex', 0)
				.change(function() {
					let lines = $(this).parents('tr').next().find('div');
					var num = $(this).val();
					lines.each(function(i, e) {
						if (num-- > 0)
							$(e).show();
						else
							$(e).hide();
					});
				})
				.appendTo(td);
				td.appendText(')【0=サポ欄非表示】');
				
				tbody.append($('<tr>').append(td));
	
				td = $('<td>', {'colspan': 4});
				let sunit = this.makeSupportUnit();
				for (let i = 0; i < this.settings.max_support; i++) {
					td.append(sunit.clone(true));
				}
				tbody.append($('<tr>').append(td));
				
				return tbody;
			},
			// サポートNPCの1体の行を生成
			makeSupportUnit: function() {
				let div = $('<div>').css('white-space', 'nowrap').hide();
				div.appendText('隠').append($('<input>', {'type': 'checkbox', 'name': 'HIDE'}));
				$('<input>', {'type': 'text', 'name': 'NAME'}).css('width', '12em').appendTo(div);
				div.appendText(' Lv.');
				$('<input>', {'type': 'number', 'name': 'LV', 'min': 0}).css('width', '3em').appendTo(div);
				div.appendText('(');
				this.tempClsSelect.clone(true).appendTo(div);
				div.appendText(')宝具Lv.');
				$('<input>', {'type': 'number', 'name': 'NOBLELV', 'min': 0, 'max': 5}).css('width', '3em').appendTo(div);
				div.appendText(' [');
				$('<input>', {'type': 'number', 'name': 'SKILL1', 'min': 0, 'max': 10}).css('width', '3em').appendTo(div);
				div.appendText('/');
				$('<input>', {'type': 'number', 'name': 'SKILL2', 'min': 0, 'max': 10}).css('width', '3em').appendTo(div);
				div.appendText('/');
				$('<input>', {'type': 'number', 'name': 'SKILL3', 'min': 0, 'max': 10}).css('width', '3em').appendTo(div);
				div.appendText(']');
				div.appendText('礼装.');
				$('<input>', {'type': 'text', 'name': 'CRAFT'}).css('width', '12em').appendTo(div);
				div.appendText('Lv.');
				$('<input>', {'type': 'number', 'name': 'CRAFTLV', 'min': 0, 'max': 100}).css('width', '3em').appendTo(div);
				return div;
			},
			getUnits: function() {
				var obj = {
					'BOLD': false,
					'HIDE': false,
					'WAVE': 0,
					'INDEX': 0,
					'NAME': '',
					'BREAK': 0,
					'LV': [],
					'SVTCLS': [],
					'HP': [],
					isEmpty : function() {
						return !this.HP || this.HP.length == 0 || !this.HP[0] || !parseInt(this.HP[0]) || !this.NAME;
					}
				};
				var units = [];
				$('.enemydecks > tr:nth-child(n+2)', this.target).each(function() {
					// 非表示WAVEに当たったら終了
					if ($(this).css('display') == 'none')
						return false;
					var unit = [];
					var nullcnt = 0;
					var wave = parseInt($(this).attr('data-wave'));
					$('td.unit', this).each(function() {
						let svt = $.extend(true, {}, obj);
						svt.BOLD = $('input[name="BOLD"]', this).prop('checked') || false;
						svt.HIDE = $('input[name="HIDE"]', this).prop('checked') || false;
						svt.WAVE = wave;
						svt.INDEX = unit.length;
						svt.NAME = $('input[name="NAME"]', this).val().trim();
						svt.BREAK= $('select[name="SHIFT"]', this).prop('selectedIndex');
						var levels = $('input[name="LV"]:visible', this);
						var classes= $('select[name="SVTCLS"]:visible', this);
						var hps = $('input[name="HP"]:visible', this);
						for (let i = 0; i < svt.BREAK+1; i++) {
							svt.LV.push($(levels[i]).val());
							svt.SVTCLS.push($(classes[i]).val());
							svt.HP.push($(hps[i]).val());
						}
						// 一番上のHP欄と名前欄が埋まってなければNULLと見なす
						if (svt.isEmpty())
							nullcnt++;
						unit.push(svt);
					});
					// 1行全て空なら終了
					if (nullcnt >= 3) {
						return false;
					}
					units = units.concat(unit);
				});
				return units;
			},
			isChecked: function(idname, tgt) {
				if (!tgt) tgt = this.target;
				return $('input[name="'+idname+'"]', tgt).prop('checked');
			},
			// 入力欄からテキスト取得(シンプル)
			getInput: function(idname, tgt) {
				if (!tgt) tgt = this.target;
				let text = $('input[name="'+idname+'"]', tgt).val();
				if (text && text.length > 0)
					return text;
				text = $('select[name="'+idname+'"]', tgt).val();
				if (text && text.length > 0)
					return text;
			},
			generate: function(phase) {
				this.phase = phase;
				let self = this;
				let text = "";
				// thead
				text += Format("|BGCOLOR({0}):CENTER:40|BGCOLOR({0}):CENTER:180|BGCOLOR({0}):CENTER:180|BGCOLOR({0}):CENTER:180|c\n", this.getBg());
				text += Format("|>|>|>|BGCOLOR({0}):COLOR(white):{1}|\n", this.getCaption(), this.getInput("QUESTNAME"));
				text += Format("|{0}{3}|>|{1}|推奨Lv.{2}|\n", this.getInput("AP1"), this.getInput("SPOT"), this.getInput("RECLV"), (this.getInput("AP2")) ? "&br()"+this.getInput("AP2") : "");
				text += Format("|~|絆P : {0}|EXP : {1}|QP : {2}|\n", toComma(this.getInput("BONDP")), toComma(this.getInput("EXP")), toComma(this.getInput("QP")));
				text += Format("|~|>|>|報酬 : {0}|\n", this.getInput("REWARD"));
				// waves : クラス構成
				let units = this.getUnits();
				let wavecnt = this.getInput("WAVECOUNT");
				let clstext = "";
				if ($('input[name="MANUALDETAIL"]', this.target).prop('checked'))
				{
					clstext = this.getInput('DECKDETAIL');
				} else {
					let counts = {};
					$.map(units, function(e, i) {
						if (e.isEmpty()) {
							return '';
						} else {
							counts[e.SVTCLS[0]] = (counts[e.SVTCLS[0]]) ? counts[e.SVTCLS[0]] + 1 : 1;
							return e.SVTCLS[0];
						}
					});
					for (let i = 0; i < this.settings.class_list.length; i++) {
						let key = this.settings.class_list[i];
						if (counts[key]) {
							if (clstext.length > 0)
								clstext += " ";
							clstext += key + counts[key];
						}
					}
				}
				clstext = clstext || "Battleなし";
				text += Format("|>|BGCOLOR({0}):{1} 全{2}回|>|BGCOLOR({0}):{3}|\n", this.getBold(), this.getInput("QID"), wavecnt, clstext);
				// waves : ユニット
				let lastwave = 0;
				for (let i = 0; i < units.length; i++) {
					let svt = units[i];
					if (i % 3 == 0) {
						if (svt.WAVE == lastwave) {
							text += "|~|";
						} else {
							text += Format("|{0}/{1}|", svt.WAVE, wavecnt);
						}
						lastwave = svt.WAVE;
					}
					if (!svt.isEmpty()) {
						let nm = svt.NAME;
						if (svt.BOLD)
							nm = "''"+svt.NAME+"''";
						if (svt.HIDE)
							nm = "&openclose2(){" + nm + "}";
						text += nm;
						for (let s = 0; s <= svt.BREAK; s++) {
							text += Format("&br()Lv{0}({1})", svt.LV[s], svt.SVTCLS[s]);
							if (svt.BREAK > 0)
								text += Format("&spanclass(break{0}{1})", svt.BREAK, svt.BREAK - s);
							text += Format(" HP{0}", toComma(svt.HP[s]));
						}
					} else {
						// 空欄は灰色に
						text += "BGCOLOR(#ccc):";
					}
					text += '|';
					if (i % 3 == 2)
						text += '\n';
				}
				// サポートNPC
				{
					if (this.getInput('SUPNUM') !== '0') {
						text += Format("|>|>|>|BGCOLOR({0}):サポートNPC|\n", this.getBold());
						let atfirst = true;
						text += "|>|>|>|";
						$('.support div:visible', this.target).each(function() {
							if (!atfirst) {
								text += "&br()";
							}
							atfirst = false;
							let nm = $('input[name="NAME"]', this).val();
							if ($('input[name="HIDE"]', this).prop('checked'))
								nm = "&openclose2(){"+nm+"}";
							text += Format("{0} Lv.{1}({2})宝具Lv.{3} [{4}/{5}/{6}]",
								nm,
								$('input[name="LV"]', this).val() || '??',
								$('select[name="SVTCLS"]', this).val(),
								$('input[name="NOBLELV"]', this).val() || '-',
								$('input[name="SKILL1"]', this).val() || '-',
								$('input[name="SKILL2"]', this).val() || '-',
								$('input[name="SKILL3"]', this).val() || '-');
							let cename = $('input[name="CRAFT"]', this).val().trim();
							if (0 < cename.length) {
								text += Format(" {0}Lv.{1}", cename, $('input[name="CRAFTLV"]', this).val() || '??');
							}
						});
						text += "|\n";
					}
				}
				// エネミー
				{
					$('.enemydetail', this.target).each(function() {
						// 左列行数=0なら非表示
						if ($('select[name="LEFTNUM"]', this).prop('selectedIndex') == 0)
							return true;
						// ヘッダ行
						let nm = self.getInput('NAME', this);
						if (self.isChecked('HIDE', this))
							nm = "&openclose2(){"+nm+"}";
						text += Format("|>|>|>|BGCOLOR({0}):エネミー《{1}》|\n", self.getBold(), nm);
						
						let righttexts = $('textarea[name="RIGHTTEXT"]:visible', this);
						let cnt = 0;
						$('input[name="LEFTTEXT"]:visible', this).each(function() {
							for (let i = 0; i < parseInt(self.getInput('RIGHTNUM', $(this).parent())); i++) {
								if (i == 0) {
									text += Format("|>|{0}|", $(this).val());
								} else {
									text += "|>|~|";
								}
								text += Format(">|{0}|\n", $(righttexts[cnt++]).val().split('\n').join('&br()'));
							}
						});
					});
				}
				// 備考
				{
					let etc = $('input[name="ETCON"]', this.target);
					if (etc.prop('checked')) {
						text += Format("|>|>|>|BGCOLOR({0}):備考|\n", this.getBold());
						text += Format("|>|>|>|CENTER:{0}|\n", etc.parents('tbody').find('textarea[name="TEXT"]').val().split('\n').join('&br()'));
					}
				}
				return text;
			},
		};
		
		return function(target, options) {
			return new QuestGen(target, options);
		};
	})();
	
	$(function(){
		// 入力欄作成
		var gen = QuestGen($('#here'), {'design': 0});
		gen.makeTable();
		
		$('#createBtn').click(function() {
			let text = gen.generate();
			if (!text) {
				text = 'ここにwiki編集用の文字列が表示されます [出力失敗]';
			}
			$('textarea[name="out"]').val(text);
		});
		
		// 入力消去ボタンの誤操作用ロック
		$('.clearbtn').prop('disabled', true);
		$('#clearLock').change(function() {
			$('.clearbtn').prop('disabled', $(this).prop('checked'));
		});
		// テーブル色変更
		$('select[name="design"]').change(function() {
			let val = $(this).val();
			gen.setDesign(val);
		});
	});
	
	</script>
}}}}}
	
#html2{
	<div>
	<form name="form0" id="form0">
	<textarea name="out" cols="150" rows="20" style="height:100px!important;text-align:left!important;">ここにwiki編集用の文字列が表示されます</textarea></br>
	<select style="width:11em;" name="design">
		<option value="0" selected>シナリオ</option>
		<option value="1">フリー・強化</option>
		<option value="2">幕間・高難易度</option>
	</select>
	<span style="margin-left:20px"><label><input type="checkbox" id="clearLock" checked>[消]ボタンロック</label></span>
	</form>
	<form name="form1" id="form1">
	<input type="button" value="作成" id="createBtn" style="width:4em;">
	<div id="here"></div>
	</form>
	
	<div class="template" style="display:none;">
		<table class="phase" cellspacing="1" border="0">
			<thead>
				<tr><td colspan="4" class="headrow">クエスト名 : <input type="text" style="width:15em;" name="QUESTNAME" /></td></tr>
				<tr>
					<td rowspan="3" style="width:80px;"><input type="text" style="width:4em;text-align:center;" name="AP1" value="AP"><br><input type="text" style="width:4em;text-align:center;" name="AP2" /></td>
					<td colspan="2">地名<input type="text" style="width:10em;" name="SPOT" /></td>
					<td>推奨Lv.<input type="text" style="width:4em;" name="RECLV" /></td>
				</tr>
				<tr>
					<td style="width:300px;">絆P : <input type="number" min="0" style="5em;" name="BONDP" /></td>
					<td style="width:300px;">EXP : <input type="number" min="0" style="5em;" name="EXP" /></td>
					<td style="width:300px;">QP : <input type="number" min="0" style="5em;" name="QP" /></td>
				</tr>
				<tr><td colspan="3">報酬 : <input type="text" style="width:15em;" name="REWARD" /></td></tr>
			</thead>
		</table>
	</div>
	</div>
}