var MAX_PLV_ = 60;//人物最高等级LV

//技能点任务
//名前,取得SP量,可以进行任务的LV
var def_sp_quests_ = [
	"培育小毛孩武道家2"         , 5,20,
	"锻炼身体之道（实战篇）"      , 5,22,
	"武道家资格考试"              ,10,22,
	"成为专业之道2"               ,30,25,
	"Unholy Sorcress 2"           ,20,10,
	"像风一样10"                , 5,18,
	"像风一样11"                , 5,20,
	"像风一样12"                , 5,23,
	"修行任务"                    ,20,15,
	"妖精们的魔法阵2"           ,20,15,
	"魔力抽出 -暗属性篇-"         , 5,29,
	"调查GBL神殿"                 , 5,26,
	"希亚西斯的预言书3"           , 5,29,
	"收集防具材料"                , 5,30,
	"恐怖的克雷库特"          , 5,27,
	"圣职者=依雷普斯的委托"  ,10,36,
	"感谢的印记"                  ,20,34,
	"血钢"            , 5,34,
	"令彷徨的灵魂安息"          ,15,34,
	"安乐的沉睡吧"              ,10,34,
	"分解成粉末的死龙身体"  ,25,39,
	"一时的允许"                ,10,33,
	"冰精灵西斯科"              ,10,40,
	"斯卡迪女王的新书"        ,20,40,
	"不能追溯的时间3" ,30,47,
	"觉醒任务"                    ,20,48,
	"盗贼团的头目"                ,30,47,
];
function getSpQuests(){
//	if(!("sp_quests_" in window)){//宣言されていなければデフォルトの物を使用．
		return def_sp_quests_;
//	}
//	return sp_quests_;
}


var need_shim_ = false;

//GUIのヒント．
//idとして有効なものは自動でonmouseoverとonmouseoutを設定している．
//複数箇所で使用するものは直接onHint(e, tag)でtagを指定すること．
var hints_ = {
	//asps_common.htmlt
	minus10btn : "角色等级-10．<br>自动习得设定的技能会自动降低技能等级．",
	minus1btn  : "角色等级-1．<br>自动习得设定的技能会自动降低技能等级．",
	plus1btn   : "角色等级+1．<br>自动习得设定的技能自动提升技能等级．",
	plus10btn  : "角色等级+10．<br>自动习得设定的技能自动提升技能等级．",
	plv        : "表示/设定现在角色的等级．",
	quest_sp   : "表示通过技能点任务取得的技能点合计量．",
	dsp        : "可以直接输入技能点的差值(只能正数)．",
	used_sp    : "现在设定了的技能所需技能点合计．",
	rest_sp    : "显示剩余的SP．",
	quest_btn  : "显示/非显示技能点任务．",
	hint_chk   : "显示/非显示帮助．",
	requirements_chk : "显示/不显示前提技能的等级．",
	slotnumber : "保存现在的设定到指定插槽．",
	load_btn      : "读取置顶插槽的数据．<br>丢弃现在显示的设定．",
	save_btn      : "把现在的设定保存到置顶插槽．",
	reset_btn     : "现在显示的设定初始化．<br>保存的设定不会被影响．",
	del_cookie_btn: "删除cookie．<br>删除所有保存了的设定．",
	skillcode     : "显示技能代码(现在的设定文字化的东西)．<br>显示需要Encode按钮，<br>从技能代码恢复的情况下需要这里输入然后按Decode按钮．",
	decode_btn    : "从技能代码来恢复设定．<br>丢弃现在的设定．",
	encode_btn    : "按现在的设定生成技能代码．",
	shortcode_chk : "技能代码的外观缩短．<br>比例字体使用不了的话长度不会变化．",
	url_chk       : "给技能代码附上URL．",
	dump_btn      : "现在的设定输出为可粘帖用文本．<br>文本导出在画面的下方显示．",
	//asps.js 
	spq_check_btn : "选择全部任务．",
	spq_clear_btn : "取消选择全部任务．",
	spq_chkbtn    : "加算被选择了的任务的技能点．",
	spq_auto_chk  : "检查对应玩家的等级可以进行的技能点任务．",
	am : "切换自动习得技能的使用．<br>选择的技能等级对应角色等级<br>自动取得最高．",
	emp_skill : "根据前提条件背景颜色会发生变化．<br>"
	           +"<span class=target_skill>选择的技能是这种色</span>，<br>"
	           +"<span class=prereq_skill>前提的技能是这种色</span>，<br>"
	           +"<span class=target_skill>选择的技能</span>是前提技能的话<span class=concl_skill>上级技能用这种颜色</span>来表示．",
	skill_select : "选择技能等级．<br>根据前提条件自动学习必须的技能，<br>前提技能等级不够的话，上级技能自动变为0．",
	output_sel_btn : "选择技能文本导出．",
	chk_fixedfont  : "使用/不使用转换固定长度的字体．<br>使用模板时强制使用比例字体．",
		chk_template   : "使用论坛连接用模板．<br>对应不了的职业不显示．",
	hideoutput_btn : "不显示技能文本导出区域．",
	dumped_text    : "显示技能文本导出．"
	
};
//new Array();してhints_["hoge"]="moke";式の初期化はIEだと処理が走らない．

function initAsps(jobname){
	setJobName(jobname);
	new Ajax.Request("asps_common.htmlt", {method:'get', onComplete: onFormLoad});
}

function onFormLoad(rho){
	$("divform").innerHTML = rho.responseText;
	printSpQuests("sp_quest_table", getSpQuests());
	printSkills("common_skill_table", common_skills_);
	printSkills("first_skill_table", first_job_skills_);
	printSkills("second_skill_table", second_job_skills_);
	loadSlots(0, true);
	var i = location.href.search(/\?/)
	var sc = (i!=-1);
	if(sc){
		var scode = location.href.substring(i+1);
		$("skillcode").value = scode;
	}
	//ヒント用のイベントハンドラを設定
	for(var i in hints_){//for inは配列の列挙ではなくオブジェクトのプロパティの列挙．
		if($(i)==undefined)continue;//idとして無効なものははじく
		//var e = $(i);
		//e.addEventListener("mousemove", onHint, false);//IEが対応してない
		Event.observe(i, "mousemove", onHint, false);//prototype.jsを利用
		Event.observe(i, "mouseout", hideHint, false);
	}
	//IE6のselect z-indexバグへの対応
	need_shim_ = (typeof document.body.style.maxHeight == "undefined");//IE6 or older
	//console.log(need_shim_);
	$("hint_area").hide();
	$("shim").hide();
	$("output_area").hide();
	
	if(sc){//スキルコード付きなら
		doDecode();
	}
}

function toggleQuestPane(){
	var t = $("sp_quest_table");
	t.toggle();
}

function printSpQuests(target, quests){
	var html = 
		'<table class="'+target+'">'+
		'<tr>'+
		'	<td colspan=3>'+
		'		<input id=spq_check_btn type=button name="on" value="选择" onClick="allcheck(this.form)">'+
		'		<input id=spq_clear_btn type="button" name="off" value="解除" onClick="allclear(this.form)"></td>'+
		'	<td><input id=spq_auto_chk type=checkbox onclick="toggleAutoSpQuest();"></td>'+
		'</tr>'+
		'<tr><th colspan=2>任务名</th><th>SP</th><th>LV</th></tr>';

	var tmp = new Template('<tr><td><input onClick="q(this.form)" type=checkbox name="quest" value="#{sp}" onmousemove="onHint(event, \'spq_chkbtn\')" onmouseout="hideHint()"></td><td>#{name}</td><td class=num>#{sp}</td><td class=num>#{lv}</td></tr>');
	for(var i=0;i<quests.length;i+=3){
		html += tmp.evaluate({name : quests[i], sp:quests[i+1], lv:quests[i+2]});
	}
	html += '</table>';
	$("sp_quest_table").innerHTML = html;
}

//スキルについて
//c1. スキルLV1から最大スキルレベルまで固定プレイヤーLV, 固定SPで上昇するもの ex.古代の記憶
//c2. スキルLV1のみSP0で取得出来，それ以外はc1と同じ． ex.ミューズアッパー
//c3. スキルLV1のみ取得SP量が違い，それ以外はc1と同じ．ex.三段切り
//c4. スキルLV1と2の取得SP量が違い，それ以外はc1と同じ． ex. アッシュ，スラスト，鬼切り，ウェーブ
//c5. スキルLV1のみ取得可能なもの
//c6. 取得可能LVで1無料取得出来，さらにLV2に上げられる． ex.覚醒パッシブスキル
//cx. 上昇パターンがそれ以外のもの
//職情報
var id_name_table_ = new Array();
var SkillInfo = Class.create();
SkillInfo.prototype = {
	//id, 日本語名
	initialize : function(id, name){
		this.id      = id;
		this.name    = name;
		this.can_learn_and_raise = false;

		this.option_zero = '<option slv=0 llv=0 value=0>无</option>';
		this.option_template = new Template('<option slv=#{slv} llv=#{llv} value=#{sum}>#{slv}) LV#{llv} [#{sum}]');
		this.options = "";
		id_name_table_[id] = name;
	},
	//習得してMなスキル 習得可能LV, 消費SP
	setAsOneOnly : function(learn_from, sp_cost){
		this.learn_from = learn_from;
		this.sp_cost = sp_cost;
		this.max_slv = 1;
		this.lv_cost = 0;
		this.first_sp_cost = sp_cost;
		this.second_sp_cost = 0;
		return this;
	},
	//基本的なタイプのスキル 習得開始LV，消費SP，次スキルLVに上げるのに必要なプレイヤーLV，最大スキルLV
	//最大スキルLVを-1指定or指定しないすることでMAX_PLV_で取得できるLVまで上げられる．
	//最大スキルLVが現状のLVキャップで取得できない場合は切り詰める．
	//習得可能プレイヤーLVでスキルLVを2にあげられる場合は最後にtrueを指定．
	//また，その場合は自動的にfirst_sp_costを0にしている．
	setAsBasic : function(learn_from, sp_cost, lv_cost, max_slv, can_learn_and_raise){
		this.learn_from   = learn_from;
		this.lv_cost      = lv_cost;
		this.sp_cost      = sp_cost;
		this.can_learn_and_raise = can_learn_and_raise;
		if(max_slv==undefined || max_slv==-1 || learn_from+(max_slv-1)*lv_cost > MAX_PLV_){
			this.max_slv = Math.floor((MAX_PLV_-learn_from)/lv_cost) + 1;
			if(this.can_learn_and_raise){
				this.max_slv += 1;
			}
		}else{
			this.max_slv = max_slv;
		}
		
		this.first_sp_cost = can_learn_and_raise?0:sp_cost;
		this.second_sp_cost = sp_cost;
		return this;
	},
	//初回消費SPのみ変更する
	setFirstCost : function(fcost, scost){
		this.first_sp_cost = fcost;
		if(scost!=undefined){
			this.second_sp_cost = scost;
		}
		return this;
	},
	//スキルLV，習得可能プレイヤーLV，消費SPの配列を指定する
	setAsRandom : function(ss){
		this.options = "";
		var i = 0;
		if(ss[0]==0){//スキルLV0設定がある場合
			this.options += this.option_zero;
			i += 3;
		}
		for(;i<ss.length;i+=3){
			this.options += this.option_template.evaluate(
				{slv : ss[i], llv : ss[i+1], sum : ss[i+2]});
		}
		this.max_slv = ss[i-3];
		//2次元配列だとうまくいかんなぁ
		//ss.each(function(s){
		//	this.options += this.option_template.evaluate(
		//		{slv : s[0], llv : s[1], sum : s[2]});
		//});
		return this;
	},
	makeOptionsHTML : function(){
		if(this.options != "")return;
		if(this.first_sp_cost != 0)
			this.options = this.option_zero;
		var base = this.learn_from;
		//LV1と2は特別扱い．鬼いやらしいです(　＾ω＾)
		//LV1
		this.options += this.option_template.evaluate(
			{slv : 1,
			 llv : base,
			 sum : this.first_sp_cost});
		if(this.can_learn_and_raise){
			base -= this.lv_cost;
		}
		//LV2～
		for(var i=1;i<this.max_slv;i++){
			this.options += this.option_template.evaluate(
				{slv : (i+1),
				 llv : base                                     +     i*this.lv_cost,
				 sum : this.first_sp_cost + this.second_sp_cost + (i-1)*this.sp_cost});
		}
	}
};

//レコード単位で前提関係の強調，ラベル/selectで不正取得の強調をする．
var record_template_ = new Template(
'<tr id="record_#{id}"><td id="label_#{id}" onmouseover="emphasizeRequirements(event, \'#{id}\');" onmouseout="hideHint()">#{name}</td>'+
'<td><input type="checkbox" name="automaster" id="am_#{id}" onclick="am(this,\'#{id}\');" onmouseover="onHint(event, \'am\');" onmouseout="hideHint();"></td>'+
//'<td><input type="edit" name="ammax" size=2></td>'+
'<td><select name="skills" id="#{id}" onchange="checkRequirements(\'#{id}\');s(this.form);" onmouseover="onHint(event, \'skill_select\')" onmouseout="hideHint()">'+
'#{options}'+
'</select></td></tr>');

function getRecordOf(id){
	return $("record_" + id);
}
function getLabelOf(id){
	return $("label_" + id);
}

function printSkills(target, skills){
	var ih = "<table class=" + target + ">";
	skills.each(function(si){
		si.makeOptionsHTML();
		ih += record_template_.evaluate(si);
	});
	ih += "</table>";
	$(target).innerHTML = ih;
}
function getCurrentSkillAttribute(id, attr){
	var sel = $(id);
	return parseInt(sel.options[sel.selectedIndex].getAttribute(attr));
}
	
function getCurrentSkillLearnLevel(id){
	return getCurrentSkillAttribute(id, "llv");
}

function getCurrentSkillLevel(id){
	return getCurrentSkillAttribute(id, "slv");
}

function setSkillLevel(id, slv){
	//console.log("setSkillLeve(id=%s, slv=%d)", id, slv);
	//スキルLV自体は0か1からしか始まらない
	return setSkillLevelOf($(id), slv);
}
function setSkillLevelAt(idx, slv){
	return setSkillLevelOf($("mainform").skills[idx], slv);
}
function setSkillLevelOf(sel, slv){
	var first_slv = parseInt(sel.options[0].getAttribute("slv"));
	if(sel.selectedIndex == slv-first_slv){
		return false;//変化無し
	}
	sel.selectedIndex = slv-first_slv;
	return true;//変更
}

var targeted_skill_id_ = null;
var emphasized_skills_ = new Array();
var prev_req_hint_ = "";
var req_hint_ = "";
function emphasizeRequirements(e, id){
	if(targeted_skill_id_==id){
		if(show_hint_){
			req_hint_ = prev_req_hint_;
			onHint(e, "emp_skill");
		}
		return;
	}
	if(targeted_skill_id_!=null){
		emphasized_skills_.each(function(tr){
			tr.className = "";
		});
		emphasized_skills_.clear();
		targeted_skill_id_ = null;
	}
	var ss = skill_requirements_;
	var pre_hint = "";
	var concl_hint = "";
	for(var i=0;i<ss.length;i+=3){
		if(ss[i] == id){//前提
			//var tr = $(ss[i+1]).parentNode.parentNode; // <select>→<td>→<tr>
			var tr = getRecordOf(ss[i+1]);
			tr.className = "concl_skill";
			emphasized_skills_.push(tr);
			//ややこしいので前提だけ表示
			//concl_hint += "<tr><td class=num>" + ss[i+2] + "<td class=concl_skill>" + id_name_table_[ss[i+1]];
		}else if(ss[i+1] == id){//前提が必要なスキル
			//var tr = $(ss[i]).parentNode.parentNode; // <select>→<td>→<tr>
			var tr = getRecordOf(ss[i]);
			tr.className = "prereq_skill";
			emphasized_skills_.push(tr);
			pre_hint += "<tr><td class=prereq_skill>" + id_name_table_[ss[i]] + "<td class=num>" + ss[i+2]
		}
	}
	if(emphasized_skills_.length!=0){
		var tr = getRecordOf(id);
		tr.className = "target_skill";
		emphasized_skills_.push(tr);
		targeted_skill_id_ = id;
	}
	req_hint_ = "";
	if(pre_hint!=""){
		req_hint_ += "<table class=prereq_hint_table><tr><th>前提技能<th>必要等级" + pre_hint + "</table>";
	}
	//ややこしいから前提だけ表示することにする
	//if(concl_hint!=""){
	//	req_hint_ += "<table class=concl_hint_table><th>必要LV<th>上位スキル" + concl_hint + "</table>";
	//}
	prev_req_hint_ = req_hint_;
	onHint(e, "emp_skill");
}

//問題なければtrueを返す．
function checkSkillLearnLevel(id){
	//プレイヤーLVが足りないものはスタイルを変えて強調
	if(getCurrentSkillLearnLevel(id)>getPlayerLv()){
		getLabelOf(id).addClassName("skill_overlevel");//レコード単位だけだとselectの文字色が変わらない
		$(id).addClassName("skill_overlevel");
		return false;
	}
	getLabelOf(id).removeClassName("skill_overlevel");
	$(id).removeClassName("skill_overlevel");
	return true;
	
}
function checkRequirements(id){
	var slv = getCurrentSkillLevel(id);
	checkSkillLearnLevel(id);
	//console.log("checkRequirements(id=%s) slv=%d", id, slv);
	var ss = skill_requirements_;
	for(var i=0;i<ss.length;i+=3){
		if(ss[i] == id){//前提
			if(getCurrentSkillLevel(ss[i+1])!=0){//前提を必要としているスキルを習得しているが
				if(slv<ss[i+2]){//必要条件に足りなくなったら
					if(setSkillLevel(ss[i+1], 0)){//習得をやめる
						checkRequirements(ss[i+1]);//変化があれば再帰．ループってこわくね？
					}
				}
			}
		}else if(slv!=0 && (ss[i+1] == id)){//前提が必要なスキル
			if(getCurrentSkillLevel(ss[i])<ss[i+2]){//前提が足りてなかったら
				if(setSkillLevel(ss[i], ss[i+2])){//取得する
					checkRequirements(ss[i]);
				}
			}
		}
	}
}
//script.js取り込み
function re(f){
	f.re.value = (parseInt(f.lv.value)+58)*(parseInt(f.lv.value)-1)/2 + parseInt(f.book.value) + parseInt(f.input.value) - parseInt(f.sum.value);
	if(f.re.value<0){
		//f.re.addClassName("sp_minus");
		Element.addClassName("rest_sp", "sp_minus");
	}else{
		//f.re.removeClassName("sp_minus");//なぜかbokunenjin鯖だけでエラーが出る？
		Element.removeClassName("rest_sp", "sp_minus");//こっちの書き方なら問題ないっぽい
		//$("rest_sp").removeClassName("sp_minus");//これでもOK
	}
}

function getPlayerLv(){
	return parseInt($F("plv"));
}
function getSpSum(){
	return parseInt(getSpByLV()) + parseInt(getQuestSp()) + parseInt(getInputSp());
}
function getSpByLV(){
	var plv = getPlayerLv()
	return (plv+58)*(plv-1)/2;
}
function getQuestSp(){
	return $F("quest_sp");
}
function getInputSp(){
	return $F("dsp");
}
function getUsedSp(){
	return $F("used_sp");
}
function getRestSp(){
	return $F("rest_sp");
}
	

function q(f){
var tmp = 0;
 for (var i=0; i<f.quest.length; i++){
  if (f.quest[i].checked == true){
   tmp += parseInt(f.quest[i].value);
  }
 }
f.book.value = tmp;
re(f);
}

function allcheck(f){
 for(var i=0; i<f.quest.length; i++){
  f.quest[i].checked = true;
 }
 q(f);
}
function allclear(f){
 for(var i=0; i<f.quest.length; i++){
  f.quest[i].checked = false;
 }
 q(f);
}
//---script.js

function clearCookie(){
	if(!confirm("删除cookie吗?\n(删除所有保存的数据)"))return;
	var expires = "=hoge;expires=Fri, 31-Dec-1999 23:59:59 GMT;";
	document.cookie = job_name_ + "data" + expires;
	alert("Cookie cleared!");
}

function save(){
	var cdata = "";

	var mf = document.getElementById("mainform");

	var slot = parseInt(mf.slotnumber.value);
	var memo = prompt("插槽No." + slot + "保存．\n请输入标题．", mf.slotnumber.options[slot].text.substr(3));
	if(memo == null)return;
	if(memo.length>30){
		memo = memo.substring(0, 30);
	}
	//update slot options memo
	var opt = mf.slotnumber.options[slot];
	opt.text = slot + ") " + memo;

	cdata += escape(memo) + ",";
	cdata += encode(0);//non-lazy encode

	//いったんロードして他のデータを拾う
	var olddata = loadDataFromCookie();
	var newdata = job_name_ + "data=";
	var slots = olddata.split(",");
	for(var i=0;i<10;i++){//スロット数は10
		if(i==slot){
			newdata += cdata + ",";
		}else{
			if(slots[i*2] != undefined && slots[i*2+1]!=undefined){
				newdata += slots[i*2] + "," + slots[i*2+1] + ",";
			}else{
				newdata += ",,";
			}
		}
	}
	
	var exp = new Date();
	exp.setTime(exp.getTime()+30*24*60*60*1000);//30日保存
	var exp_str = "; expires=" + exp.toGMTString();
	newdata += exp_str;
	
	document.cookie = newdata;
	
}
//function save_old(){
//	var mf = document.getElementById("mainform");
//
//	var slot = parseInt(mf.slotnumber.value);
//	var memo = prompt("Saving slot " + slot + ". Enter a title for this setting.", mf.slotnumber.options[slot].text.substr(3));
//	if(memo == null)return;
//	var exp = new Date();
//	exp.setTime(exp.getTime()+30*24*60*60*1000);//30日保存
//	var exp_str = "; expires=" + exp.toGMTString();
//	document.cookie = slot + job_name_+"memo="+ escape(memo) + exp_str;
//
//	document.cookie = slot + job_name_+"plv=" + $F("plv") + exp_str;
//	document.cookie = slot + job_name_+"dsp=" + $F("dsp") + exp_str;
//	
//	//update slot options memo
//	var opt = mf.slotnumber.options[slot];
//	opt.text = slot + ") " + memo;
//	
//	var qq = document.getElementsByName("quest");
//	var qlist = slot + job_name_+"qlist=";
//	for(var i=0;i<qq.length;i++){
//		qlist += qq[i].checked?"1,":"0,";
//	}
//	//alert(qlist);
//	document.cookie = qlist + exp_str;
//	
//	var ss = document.getElementsByName("skills");
//	var slist = slot + job_name_+"slist=";
//	for(var i=0;i<ss.length;i++){
//		slist += ss[i].options[ss[i].selectedIndex].getAttribute("slv") + ",";
//	}
//	//alert(slist);
//	document.cookie = slist + exp_str;
//	
//	var aa = document.getElementsByName("automaster");
//	var alist = slot + job_name_+"alist=";
//	for(var i=0;i<aa.length;i++){
//		alist += aa[i].checked?"1,":"0,";
//	}
//	//alert(alist);
//	document.cookie = alist + exp_str;
//	alert("slot " + slot + " saved.");
//}
function load(){
	var mf = document.getElementById("mainform");
	var slot = mf.slotnumber.value;
	if(!confirm("插槽No." + slot + "读取吗?"))return;
	clearForm();
	loadSlots(slot, false);
}

var job_name_ = "";
function setJobName(name){
	job_name_ = name;
}
function loadDataFromCookie(){
	//hoge=moke; b=c; d=g
	var cc = document.cookie;
	//データ部分の切り出し
	var ll = cc.split(";");
	var data = "";
	var varname = job_name_ + "data=";
	for(var i=0;i<ll.length;i++){
		if(ll[i].strip().indexOf(varname)==0){
			data = ll[i].strip().substring(varname.length);
			break;
		}
	}
	return data;
}
function loadSlots(slot, load_all){
	var mf = document.getElementById("mainform");
	mf.slotnumber.selectedIndex = slot;
	var data = loadDataFromCookie();
	if(data==""){
		//no saved data
		return;
	}
	var slots = data.split(",");
	for(var i=0;i<10;i++){
		if(!load_all && i!=slot)continue;//単品読み込みなら指定スロット以外は飛ばす
		if(load_all){
			if(i*2<slots.length){
				memo = unescape(slots[i*2]);
			}else{
				memo = "";
			}
			if(memo==""){
				memo = "untitled";
			}
			mf.slotnumber.options[i].text =  i + ") " + memo;
		}
		if(i!=slot)continue;//指定スロット以外はメモ以外を読む必要は無い
		if(i*2+1<slots.length){
			decode(slots[i*2+1]);
		}
		if(!load_all)break;//スロット単品読み込みなら終了
	}
}
//function loadSlots_old(slot, load_all){
//	//console.log("loadSlots(slot=%d, load_all=%d)", slot, load_all);
//	var mf = document.getElementById("mainform");
//	mf.slotnumber.selectedIndex = slot;
//	var cc = document.cookie;
//	//console.log(cc);
//	//alert(cc);
//	var ll = cc.split(";");
//	//alert(ll.length);
//	for(var i=0;i<ll.length;i++){
//		idx = parseInt(ll[i]);
//		//alert("i=" + i + "\nidx=" + idx + "\nll[i]=" + ll[i]);
//		if(!load_all && idx!=slot)continue;//単品読み込みなら指定スロット以外は飛ばす
//		list = ll[i].split("=")[1];
//		if(load_all){
//			if(ll[i].indexOf(job_name_+"memo=")!=-1){//全読み込みのときはメモだけ読む
//				memo = unescape(list);
//				mf.slotnumber.options[idx].text = idx + ") " + memo;
//			}
//			if(idx!=slot)continue;
//		}
//		
//		if(ll[i].indexOf(job_name_+"plv")!=-1){
//			$("plv").value = list;
//			continue;
//		}
//		if(ll[i].indexOf(job_name_+"dsp")!=-1){
//			$("dsp").value = list;
//			continue;
//		}
//		
//		vv = list.split(",");
//		//alert("vv.length=" + vv.length);//vvは配列要素が一つ多いので注意
//		if(ll[i].indexOf(job_name_+"qlist")!=-1){
//			var qq = document.getElementsByName("quest");
//			//alert("qlist, qq.length="+ qq.length);
//			for(j=0;j<qq.length;j++){
//				qq[j].checked = parseInt(vv[j]);
//			}
//		}else if(ll[i].indexOf(job_name_+"slist")!=-1){
//			var ss = document.getElementsByName("skills");
//			//alert("slist, ss.legnth=" + ss.length);
//			for(j=0;j<ss.length;j++){
//				if(vv[j] == 0){//スキルレベル0ならインデックスは必ず0
//					ss[j].selectedIndex = 0;
//				}else{
//					//インデックスと一致しないなら-1(1レベル自動習得スキル)
//					if(ss[j].options.length>vv[j] && ss[j].options[vv[j]].getAttribute("slv") == vv[j]){
//						ss[j].selectedIndex = vv[j];
//					}else{
//						ss[j].selectedIndex = parseInt(vv[j])-1;
//					}
//				}
//			}
//		}else if(ll[i].indexOf(job_name_+"alist")!=-1){
//			var aa = document.getElementsByName("automaster");
//			//alert("aa.length=" + aa.length);
//			for(j=0;j<aa.length;j++){
//				aa[j].checked = parseInt(vv[j]);
//			}
//		}
//	}
//	q(mf);
//	s(mf);
//}

function onSlotChange(sel){
	
}

function s(f){
	var ss = document.getElementsByName("skills");
	var sum = 0;
	for(var i=0;i<ss.length;i++){
		sum += parseInt(ss[i].value);
	}
	f.sum.value = sum;
	re(f);
}
function addLevel(dlv){
	var mf = $("mainform");
	var lv = getPlayerLv() + dlv;
	if(lv<1)lv=1;
	else if(lv>MAX_PLV_)lv=MAX_PLV_;
	$("plv").value = lv;
	if(auto_check_spq_)checkSpQuest();
	if(checkSkillLevels()){
		s(mf);
	}else{
		re(mf);
	}
	
}

function isAutoMaster(id){
	var chk = $("am_" + id);
	return chk.checked;
}

//plvの変化によるスキルレベルの変化を选择
//Automasterなら上下，そうで無いならば下降のみする．
function checkSkillLevels(){
	var mf = $("mainform");
	var plv = getPlayerLv();//player lv
	var changed = false;
	for(var i=0;i<mf.automaster.length;i++){//全てのスキルに対して
		if(mf.automaster[i].checked){
			if(applyAutomaster(plv, mf.skills[i]))changed = true;
		}else{
			if(cutOverskill(plv, mf.skills[i]))changed = true;
		}
		checkSkillLearnLevel(mf.skills[i].id);
	}
	return changed;
}

//要求pLV以下のスキルを足切りする
function cutOverskill(plv, skill_select){
	var opts = skill_select.options;//対応スキルのオプションリスト
	var cand = skill_select.selectedIndex;
	var i;
	for(i=1;i<=skill_select.selectedIndex;i++){
		var llv = opts[i].getAttribute("llv");
		//console.log("i=" + i + ", llv=" + llv + ", plv=" + plv);
		if(llv>plv){
			break;
		}
	}
	if(i==skill_select.selectedIndex+1)return false;
	skill_select.selectedIndex = i-1;
	return true;
}

function applyAutomaster(plv, skill_select){
	var opts = skill_select.options;//対応スキルのオプションリスト
	for(var j=opts.length-1;j>=0;j--){
		var llv = opts[j].getAttribute("llv");//習得可能LVを拾う
		if(llv <= plv){
			if(skill_select.selectedIndex == j){//変化なし
				return false;
			}
			var prev = skill_select.selectedIndex;
			skill_select.selectedIndex = j;//選択
			if(prev<j){//スキルレベルが上昇するなら
				checkRequirements(skill_select.getAttribute("id"));//前提条件を选择
			}
			return true;//スキルレベル変化
		}
	}
	//習得LVが2以上で自動習得スキル対策
	if(skill_select.selectedIndex == 0)return false;
	skill_select.selectedIndex = 0;
	return true;
}
function am(cb, sel_id){//automaster
	if(!cb.checked)return false;
	var select = $(sel_id);
	if(!applyAutomaster(getPlayerLv(), select))return false;
	select.onchange();
	return true;
}

function clearForm(need_confirm){
	if(need_confirm && !confirm("现在的技能情报重置吗?\n(保存了的情报不会改变)"))return;
	var def_lv = MAX_PLV_;
	$("plv").value = def_lv;
	$("dsp").value = 0;
	var mf = $("mainform");
	for(var i=0;i<mf.quest.length;i++){
		mf.quest[i].checked = false;
	}
	for(var i=0;i<mf.automaster.length;i++){
		mf.automaster[i].checked = false;
	}
	for(var i=0;i<mf.skills.length;i++){
		mf.skills[i].selectedIndex = 0;
	}
	q(mf);
	s(mf);
}

//位置の調整
//01/10 M : hoge
//05/04 . . : moke
//　　　　M : nyo
// . 1/. 5 . . : moke
//　 　　　1 : hoge
var use_fixed_font_ = false;
var use_template_ = false;
function doDump(){
	$("output_area").show();
	var text = "";
	//LV SP
	text += "感谢使用多玩特制地下城与勇士加点模拟器" + "\n";
	text += "更多消息请关注我们df.duowan.com" + "\n";
	text += "LV" + getPlayerLv() + ", ";
	text += "合计技能点:" + getSpSum() + ", ";
	text += "任务技能点:" + getQuestSp() + ", ";
	text += "输入技能点:" + getInputSp() + ", ";
	text += "使用技能点:" + getUsedSp() + ", ";
	text += "剩余技能点:" + getRestSp() + "\n";
	//URL
	text += getBaseUrl().substring(1);// ttp://に
	//var i = location.href.search(/\?/);
	//if(i==-1){
	//	text += location.href.substring(1);//ttp://に
	//}else{
	//	text += location.href.substring(1, i-1);//codeをはずす
	//}
	text += "?" + encode(use_shortcode_) + "\n";
	var cr_len = 50;
	if(use_fixed_font_)cr_len = 30;
	if(!use_template_){
		text += "--------[一般技能]--------\n";
		text += getSkillDumpHTML(common_skills_, true, true, cr_len);
		text += "--------[一次转职技能]--------\n";
		text += getSkillDumpHTML(first_job_skills_, true, true, cr_len);
		text += "--------[觉醒技能/阿尔伯特技能]--------\n";
		text += getSkillDumpHTML(second_job_skills_, true, true, cr_len);
	}else{
		if(!("skill_template_" in window) || skill_template_==""){
			text += "未对应模板";
		}else{
			var tmp = skill_template_;
			tmp = getSkillDumpHTML2(tmp, common_skills_);
			tmp = getSkillDumpHTML2(tmp, first_job_skills_);
			tmp = getSkillDumpHTML2(tmp, second_job_skills_);
			text += tmp;
		}
	}
	$("dumped_text").value = text;
	
	$("chk_fixedfont").checked = use_fixed_font_;
	$("chk_template").checked  = use_template_;
}

function selectOutputArea(){
	$("dumped_text").select();
}
function hideOutputArea(){
	var dest = $("output_area");
	dest.hide();
}
//マスター済みのスキル，1しか取らないスキルをまとめるほうがいいかもしれない
//まったく覚えてないスキルでもM予定なら描画
function getSkillDumpHTML(skills, unite_mastered, unite_oneonly, cr_len){
	var text = "";
	var mastered = new Array();
	var oneonly  = new Array();
	skills.each(function(s){
		var slv = getCurrentSkillLevel(s.id);
		var am  = isAutoMaster(s.id);
		if(slv==0 && !am)return;//描画の必要なし
		
		if(slv==s.max_slv){
			if(unite_mastered){
				mastered.push(s);
			}else{
				if(use_fixed_font_){
					text += "      M : ";
				}else{
					text += "　　　　M : ";
				}
				text += s.name + "\n";
			}
		}else{
			if(unite_oneonly && slv==1 && !am){
				oneonly.push(s);
			}else{
				if(slv<10){
					if(use_fixed_font_){
						text += " ";
					}else{
						text += " . ";
					}
				}
				text += slv + "/";
				if(s.max_slv<10){
					if(use_fixed_font_){
						text += " ";
					}else{
						text += ". ";
					}
				}
				text += s.max_slv;
				if(am){
					text += " M : ";
				}else{
					if(use_fixed_font_){
						text += "   : ";
					}else{
						text += " . . : ";
					}
				}
				text += s.name + "\n";
			}
		}
	});
	if(unite_oneonly && oneonly.length !=0){
		var mt = "";
		if(use_fixed_font_){
			mt = "      1 :";
		}else{
			mt = "　 　　　1 : ";
		}
		var len = 6;
		oneonly.each(function(s){
			if(len<cr_len){
				mt += s.name + ", ";
				len+= s.name.length + 1;
			}else{
				if(use_fixed_font_){
					mt += "\n    1   : ";
				}else{
					mt += "\n　 　　　1 : ";
				}
				mt += s.name + ", ";
				len = 6 + s.name.length + 1;
			}
		});
		mt = mt.slice(0, -2); // ", "を消す
		mt += "\n";
		text = mt + text;
	}
	if(unite_mastered && mastered.length!=0){
		var mt = "";
		if(use_fixed_font_){
			mt = "      M : ";
		}else{
			mt = "　　　　M : ";
		}
		var len = 6;//半角全角のサイズの差は面倒なので全角単位で
		mastered.each(function(s){
			if(len<cr_len){
				mt += s.name + ", ";
				len+= s.name.length + 1;
			}else{
				if(use_fixed_font_){
					mt += "\n      M : ";
				}else{
					mt += "\n　　　　M : ";
				}
				mt += s.name + ", ";
				len = 6 + s.name.length + 1;
			}
		});
		mt = mt.slice(0, -2); // ", "を消す
		mt += "\n";
		text = mt + text;
	}
	return text;
}

function setDumpTextFont(){
	var font = "aa";
	if(!use_template_ && use_fixed_font_){
		font = "fixed_font";
	}
	$("dumped_text").className = font;
}

function toggleFixedFont(){
	use_fixed_font_ = !use_fixed_font_;
	$("chk_fixedfont").checked = use_fixed_font_;
	setDumpTextFont();
	doDump();
}
function toggleUseTemplate(){
	use_template_ = !use_template_;
	$("chk_template").checked = use_template_;
	setDumpTextFont();
	doDump();
}

//テンプレの置換を行う
// temp : テンプレ
// skill : 置換対象スキル名
// text  : 置換後テキスト
// closr : スキルLVをはさむ後続括弧．】とか
// need_adj : trueなら後続の　　を 　 に置換することで1dotずらす
// returns : 置換後のテンプレ
function replaceSkillTemplate(temp, skill, text, closer, need_adj){
	if(need_adj && temp.search("{" + skill + "}" + closer + "　　")!=-1){
		//調整が必要で閉じ括弧のあとに全角スペースが二つ続いた場合
		return temp.replace("{" + skill + "}" + closer + "　　", text + closer + " 　 ");//-1dot
	}
	return temp.replace("{" + skill + "}", text);
}

//テンプレを利用してスキルダンプする
//tmp : テンプレート．"{id}"がスキルLVに置換される．
//skills : スキルの配列．
//returns : 置換されたテンプレート．
//[ 　] 未取得16dot
//[ .1] 一桁  16dot
//[12]  二桁  16dot
//[Ｍ]  M取り 15dot
//Ｍ取り以外は右の　　を調整する
function getSkillDumpHTML2(tmp, skills){
	var closer = "】";
	skills.each(function(s){
		var slv = getCurrentSkillLevel(s.id);
		var am  = isAutoMaster(s.id);
		if(slv==0 && !am){
			tmp = replaceSkillTemplate(tmp, s.id, " 　", closer, true);
		}else if(am || slv==s.max_slv){
			tmp = replaceSkillTemplate(tmp, s.id, "Ｍ", closer, false);
		}else{
			var text = "";
			if(slv<10){
				text = " ." + slv;
			}else{
				text = slv;
			}
			tmp = replaceSkillTemplate(tmp, s.id, text, closer, true);
		}
	});
	return tmp;
}
var show_hint_ = false;
function toggleHint(){
	if(show_hint_ && !show_requirements_){
		hideHint();
	}
	show_hint_ = !show_hint_;
}
var hint_shown_ = false;
//ヒントを表示
//idによってユニークなものはeventからidを抽出，
//複数箇所で使用するものはtagで指定する．
function onHint(e, tag){
	if(!show_hint_ && !show_requirements_)return;
	if(hint_shown_)return;
	var a = $("hint_area");
	var obj = Event.element(e);
	var id = obj.id;
	if(tag!=undefined){
		id = tag;
	}
	a.innerHTML = ""
		+ (show_hint_?hints_[id]:"")
		+ (show_hint_&&show_requirements_?"<br>":"")
		+ (show_requirements_?req_hint_:"");
	if(a.innerHTML=="")return;//中身が無いなら表示しない
	req_hint_ = "";//クリア
	var x = Event.pointerX(e);
	var y = Event.pointerY(e);
	var cx = e.clientX;
	var cy = e.clientY;
	var w = a.getWidth();
	var h = a.getHeight();
	if(cx+w+30>document.body.clientWidth){
		x = x - 60 - w;
	}
	if(cy+h+30>document.body.clientHeight){
		y = y - 40 - h;
	}
	a.style.left = x + 30 + "px";
	a.style.top  = y + 20 + "px";
	a.show();

	if(need_shim_){//IE6とかはselectのz-indexが効かない
		var s = $("shim");
		s.style.width  = a.getWidth();
		s.style.height = a.getHeight();
		s.style.left   = a.style.left;
		s.style.top    = a.style.top;
		s.show();
	}
	hint_shown_ = true;
	Event.stop(e);
	return true;
}

function hideHint(){
	if(!show_hint_&&!show_requirements_)return;
	hint_shown_ = false;
	var a = $("hint_area");
	a.hide();
	if(need_shim_){
		var s = $("shim");
		s.hide();
	}
	return true;
}
var use_shortcode_ = true;
function toggleShortcode(){
	use_shortcode_ = !use_shortcode_;
}

function doEncode(){
	var scode = encode(use_shortcode_);
	if(append_url_){
		scode = getBaseUrl() + "?" + scode;
	}
	$("skillcode").value = scode;
}

function doDecode(){
	if(!confirm("恢复技能代码吗?(丢弃现在的设定)"))return;
	var scode = $F("skillcode");
	var i = scode.search(/\?/);
	if(i!=-1){
		scode = scode.substring(i+1);
		$("skillcode").value = scode;
	}
	clearForm();
	decode(scode);
}

var show_requirements_ = true;
function toggleShowRequirements(){
	show_requirements_ = !show_requirements_;
}

var append_url_ = true;
function toggleUrlCode(){
	append_url_ = !append_url_;
	doEncode();
}

function getBaseUrl(){
	return location.protocol + "..//" + location.host + location.pathname;
}

var auto_check_spq_ = false;
function toggleAutoSpQuest(){
	auto_check_spq_ = !auto_check_spq_;
	if(auto_check_spq_)checkSpQuest();
}
function checkSpQuest(){
	var spq = getSpQuests();
	var plv = getPlayerLv()
	var qq = document.getElementsByName("quest");
	for(var i=0;i<spq.length;i+=3){
		qq[i/3].checked = (spq[i+2]<=plv);
	}
	q($("mainform"));
}
