Greasy Fork

GLib

GBF Bot Library

目前为 2019-06-03 提交的版本。查看 最新版本

此脚本不应直接安装,它是一个供其他脚本使用的外部库。如果您需要使用该库,请在脚本元属性加入:// @require https://update.greasyfork.icu/scripts/383201/704453/GLib.js

// ==UserScript==
// @name         GLib
// @namespace    http://tampermonkey.net/
// @version      5.5
// @description  GBF Bot Library
// @author       eterNEETy
// @match        http://game.granbluefantasy.jp/
// @grant        none
// @namespace    https://greasyfork.org/users/292830
// ==/UserScript==
// jshint esversion: 6
// jshint -W138

// environment info
const xhr = new XMLHttpRequest(),
	server = "http://localhost:2487",
	margin = {"top":91,"left":0},
	game_url = "http://game.granbluefantasy.jp/";

let debug = true,
	reload_counter;

let my_profile = "Main: ";
let is_host = "false";
let player_status;

let quests_id = [], monsters = [], monsters_name = [];

// const game variable
const trial_id = "990011",
	select_summon_path = "supporter/",
	message = {
		"raid" : {
			"panel" : {
				"open" : my_profile+"Opening quest/raid panel",
				"pick" : my_profile+"Picking quest/raid difficulties",
			},
			"select_party" : my_profile+"Selecting party",
			"finish" : my_profile+"Raid finished",
			"trial" : {
				"close_pop_up" : my_profile+"In trial, closing pop up",
				"open_menu" : my_profile+ "In trial, click menu",
				"retreat" : my_profile+ "In trial, click retreat",
				"ok" : my_profile+ "In trial, click ok",
				"end" : my_profile+"Retreated from trial, back to main raid",
			}
		},
		"summon" : {
			"select" : my_profile+"Selecting summon",
			"pick_tab" : my_profile+"Clicking summon element tab",
			"not_found" : my_profile+"Support summon not found, going to trial",
		},
		"replenish" : {
			"elixir" : {
				"half_elixir" : {
					"use" : my_profile+"Not enough AP, using half elixir",
					"used" : my_profile+"Half elixir used",
				}
			},
			"soul" : {
				"soul_berry" : {
					"use" : my_profile+"Not enough EP, using soul berry",
					"used" : my_profile+"soul berry used"
				}
			}
		},
		"ok" : "Clicking ok"
	};

// path
let path = {
	"item":"#item",
	"quest":"#quest",
	"support":"#quest/supporter/",
	"assist":"#quest/assist",
	"unclaimed":"#quest/assist/unclaimed",
	"trial":"#quest/supporter/"+trial_id+"/17",
};

// element dom query selector
let skill_char = "#prt-command-top > div > div > div.lis-character";
let skill_abi = ".btn-command-character > div.prt-ability-state > div.lis-ability-state.ability";
let query = {
	"battle_ui": {
		"skill": {
			"char1": {
				"skill1": skill_char + "0" + skill_abi + "1",
				"skill2": skill_char + "0" + skill_abi + "2",
				"skill3": skill_char + "0" + skill_abi + "3",
				"skill4": skill_char + "0" + skill_abi + "4",
			},
			"char2": {
				"skill1": skill_char + "1" + skill_abi + "1",
				"skill2": skill_char + "1" + skill_abi + "2",
				"skill3": skill_char + "1" + skill_abi + "3",
				"skill4": skill_char + "1" + skill_abi + "4",
			},
			"char3": {
				"skill1": skill_char + "2" + skill_abi + "1",
				"skill2": skill_char + "2" + skill_abi + "2",
				"skill3": skill_char + "2" + skill_abi + "3",
				"skill4": skill_char + "2" + skill_abi + "4",
			},
			"char4": {
				"skill1": skill_char + "3" + skill_abi + "1",
				"skill2": skill_char + "3" + skill_abi + "2",
				"skill3": skill_char + "3" + skill_abi + "3",
				"skill4": skill_char + "3" + skill_abi + "4",
			},
		},
		"skill_pop_up": {
			"char1": "div.pop-usual.pop-select-member > div.prt-popup-body > div.prt-wrapper > div.prt-character > div.lis-character0.btn-command-character > img",
			"char2": "div.pop-usual.pop-select-member > div.prt-popup-body > div.prt-wrapper > div.prt-character > div.lis-character1.btn-command-character > img",
			"char3": "div.pop-usual.pop-select-member > div.prt-popup-body > div.prt-wrapper > div.prt-character > div.lis-character2.btn-command-character > img",
			"char4": "div.pop-usual.pop-select-member > div.prt-popup-body > div.prt-wrapper > div.prt-character > div.lis-character3.btn-command-character > img",
			"char5": "div.pop-usual.pop-select-member > div.prt-popup-body > div.prt-wrapper > div.prt-character > div.lis-character4.btn-command-character > img",
			"char6": "div.pop-usual.pop-select-member > div.prt-popup-body > div.prt-wrapper > div.prt-character > div.lis-character5.btn-command-character > img",
		},
		// "#prt-command-top > div > div > div.lis-character3.btn-command-character > div.prt-ability-state > div.lis-ability-state.ability3",
		"ougi": ".btn-lock",
		"toggle_ougi": {
			true: ".lock0",
			false: ".lock1",
		},
		"char_ico": ".prt-party>.prt-member>.btn-command-character>img.img-chara-command",
		"summon_panel": ".prt-summon-list>.prt-list-top.btn-command-summon",
		"chat":".btn-chat.comment.display-on",
		"chat_pop_up": {
			"dialog":".txt-chat-pop",
		},
		"heal":"#prt-sub-command-group>.btn-temporary",
		"heal_pop_up": {
			"green": ".lis-item.item-small",
			"blue": ".lis-item.item-large",
			"use": ".pop-usual.pop-raid-item.pop-show>.prt-popup-footer>.btn-usual-use",
			"cancel": ".pop-usual.pop-raid-item.pop-show>.prt-popup-footer>.btn-usual-cancel",
		},
		"trial_pop_up": {
			"close": ".pop-usual.pop-trialbattle-notice.pop-show>.prt-popup-footer>.btn-usual-close"
		},
	},
	"assist_ui": {
		"tab_id": "#tab-id",
		"tab_multi": "#tab-multi",
		"tab_event": "#tab-event",
		"unclaimed": ".btn-unclaimed",
	},
	"poker": {
		"canvas": "#canv",
		"deal": ".prt-start",
		"ok": ".prt-ok",
		"yes": ".prt-yes",
		"no": ".prt-no",
		"low": ".prt-double-select>.prt-low-shine",
		"high": ".prt-double-select>.prt-high-shine",
	},
	"ok":".btn-usual-ok",
};

// general item variable
let tracked_item = false;

function reloadNow() {
	console.log(reloadNow.name);
	xhr.open('POST', server);
	xhr.send(JSON.stringify([{"cmd":"press","key":"f5"}]));
	window.location.reload();
}

function reload(mod_value=1) {
	clearInterval(reload_counter);
	let current_path = window.location.hash;
	let count = 1;
	reload_counter = setInterval(function() {
		if(window.location.hash != current_path){
			clearInterval(reload_counter);
		}
		console.log("reloading in "+(mod_value-count).toString());
		if (count%mod_value===0){
			clearInterval(reload_counter);
			reloadNow();
		}
		count += 1;
	}, 1000);
}

function setDebug() {
	if(!debug){
		console.log("DEBUG is turned OFF");
		if(!window.console) window.console = {};
		let methods = ["log", "debug", "warn", "info"];
		for(let i=0;i<methods.length;i++){
			console[methods[i]] = function(){};
		}
	}
}

function readBody(xhr) {
	let data;
	if (!xhr.responseType || xhr.responseType === "text") {
		data = xhr.responseText;
	} else if (xhr.responseType === "document") {
		data = xhr.responseXML;
	} else {
		data = xhr.response;
	}
	return data;
}

function gotoHash(key){
	let hash_path;
	if (path[key] !== undefined) {
		hash_path = path[key];
	}else{
		if (key.indexOf("#")!==0) {
			hash_path = "#"+key;
		}
	}
	window.location.href = game_url + hash_path;
}

function scrollTo(query,qid=0) {
	document.querySelectorAll(query)[qid].scrollIntoViewIfNeeded();
}

function checkExist(query,qid=0) {
	let el_exist = false;
	if (document.querySelectorAll(query).length > qid){
		if (document.querySelectorAll(query)[qid].getBoundingClientRect().width > 0 && document.querySelectorAll(query)[qid].getBoundingClientRect().height > 0) {
			el_exist = true;
		}
	}
	return el_exist;
}

function checkEl(query,qid=0,callback=false) {
	let old_top = -1;
	let old_left = -1;
	let loop_checkEl = setInterval(function() {
		console.log(checkEl.name + " " + query + "[" + qid + "]");
		if (checkExist(query,qid)) {
			if (old_top==document.querySelectorAll(query)[qid].getBoundingClientRect().top && old_left==document.querySelectorAll(query)[qid].getBoundingClientRect().left) {
				clearInterval(loop_checkEl);
				if (typeof callback == "function") {
					callback();
				}
			}else{
				old_top = document.querySelectorAll(query)[qid].getBoundingClientRect().top;
				old_left = document.querySelectorAll(query)[qid].getBoundingClientRect().left;
			}
		}
	}, 200);
}

function checkEls(queries,callback=false) {
	let exist_result;
	let loop_checkEls = setInterval(function() {
		exist_result = [];
		for (let i in queries) {
			console.log(checkEls.name + " " + queries[i].query + "[" + queries[i].qid + "]");
			exist_result.push(checkExist(queries[i].query,queries[i].qid));
		}
		if (exist_result.indexOf(false)===-1) {
			clearInterval(loop_checkEls);
			if (typeof callback == "function") {
				callback();
			}
		}
	}, 300);
}

function checkError() {
    let q_cnt_error = ".cnt-error";
    let q_pop_up = ".pop-usual.common-pop-error.pop-show";
    let check_error = setInterval(function() {
        let func_name = checkError.name;
        
		if (checkExist(q_pop_up,0) || checkExist(q_cnt_error,0)) {
			let cmd = [];
			console.log("error_found");
			let do_reload = false;
			let level = "notif";
			let msg = "Uncatagorized error found";
            // let msg = "Connection error, refreshing disabled"
            if (checkExist(q_pop_up+">.prt-popup-header",0)) {
                if (document.querySelector(q_pop_up+">.prt-popup-header").innerHTML=="Access Verification") {
					clearInterval(reload_counter);
					msg = my_profile+"Captcha detected";
					console.log("Captcha detected");
                }else if (document.querySelector(q_pop_up+">.prt-popup-header").innerHTML=="エラー") {
					if (checkExist(q_pop_up+">.prt-popup-body>.txt-popup-body>div",0)) {
						if (typeof document.querySelector(q_pop_up+">.prt-popup-body>.txt-popup-body>div").innerHTML == "string") {
							if (document.querySelector(q_pop_up+">.prt-popup-body>.txt-popup-body>div").innerHTML.indexOf("Network Error")>=0) {
								clearInterval(reload_counter);
								console.log("Error connection");
								do_reload = true;
								msg = my_profile+"Error connection, reloading";
								level = "process";
							}
						}
					}
				}
            }
            if (checkExist(q_pop_up+">.prt-popup-body>.txt-popup-body",0)) {
                if (document.querySelector(q_pop_up+">.prt-popup-body>.txt-popup-body").innerHTML=="Check your pending battles.") {
                    console.log("check raid");
                    level = "process";
                    msg = my_profile+"Check your pending battle";
                    clickEl(".prt-popup-footer>.btn-usual-ok",0,my_profile+"Clicking ok pop up pending battles");
                }
            }
			if (do_reload){
				cmd.push({"cmd":"press","key":"f5"});
			}
			cmd.push({"cmd":"log","level":level,"msg":msg});
			xhr.open('POST', server);
			xhr.send(JSON.stringify(cmd));
			if (do_reload){
				window.location.reload();
			}
		}
	}, 5000);
}

function getCoord(el){
	let x, y, output;
	el = el.getBoundingClientRect();
	if (el.width>0 && el.height>0) {
		x = (el.width / 2) + el.left;
		y = (el.height / 2) + el.top;
		if(el.width>40){
			x += Math.floor(Math.random() * 41)-20;
		}else if(el.width>20){
			x += Math.floor(Math.random() * 21)-10;
		}else if(el.width>10){
			x += Math.floor(Math.random() * 11)-5;
		}
		if(el.height>10){
			y += Math.floor(Math.random() * 11)-5;
		}
		output = [x+margin.left,y+margin.top];
	}else{
		output = 0;
	}
	return output;
}

function getMarginCoord(query,qid){
	let el = document.querySelectorAll(query)[qid].getBoundingClientRect();
	return {"top":el.top+margin.top,"left":el.left+margin.left};
}

function clickNow(query,qid=0,msg=my_profile+"clickNow called",callback=false){
	let el = document.querySelectorAll(query)[qid];
	let output = false;
	if (checkExist(query,qid)) {
		output = true;
		let cmd = [];
		cmd.push({"cmd":"clickIt","param":getCoord(el)});
		cmd.push({"cmd":"log","level":"process","msg":msg});
		xhr.open("POST", server);
		xhr.send(JSON.stringify(cmd));
		if (typeof callback == "function") {
			callback();
		}
	}
	return output;
}

function clickEl(query,qid=0,msg=my_profile+"clickEl called",callback=false){
	let init_clickEl = function() {
		clickNow(query,qid,msg,callback);
	};
	checkEl(query,qid,init_clickEl);
}

function clickObject(obj){
	if (obj == "ok"){
		clickEl(".btn-usual-ok",0,message.ok);
	}
}

function clickAndNegCheck(query,qid=0,msg="clickAndNegCheck called",callback=false,ticks=5){
	let old_top = -1;
	let old_left = -1;
	let match = ticks-1;
	let str_clickAndNegCheck = clickAndNegCheck.name + ", el: " + query + "["+(qid.toString())+"] \n- match = ";
	let init_clickAndNegCheck = function() {
		let loop_clickAndNegCheck = setInterval(function() {
			console.log(str_clickAndNegCheck+(match.toString()));
			if (!(checkExist(query,qid))) {
				clearInterval(loop_clickAndNegCheck);
				if (typeof callback == "function") {
					callback();
				}
			}else{
				if (checkExist(query,qid)) {
					if (old_top==document.querySelectorAll(query)[qid].getBoundingClientRect().top && old_left==document.querySelectorAll(query)[qid].getBoundingClientRect().left) {
						if (match % ticks == 0) {
							clickNow(query,qid,msg);
						}
						match += 1;
					}else{
						old_top = document.querySelectorAll(query)[qid].getBoundingClientRect().top;
						old_left = document.querySelectorAll(query)[qid].getBoundingClientRect().left;
					}
				}
			}
		}, 100);
	};
	checkEl(query,qid,init_clickAndNegCheck);
}

function clickAndCheck(query1,qid1=0,query2,qid2=0,msg="clickAndCheck called",callback=false,ticks=5){
	let old_top = -1;
	let old_left = -1;
	let match = ticks-1;
	let str_clickAndCheck = clickAndCheck.name + ", check: " + query2 + "["+(qid2.toString())+"], click: " + query1 + "["+(qid1.toString())+"] \n- match = ";
	let loop_clickAndCheck = setInterval(function() {
		console.log(str_clickAndCheck+(match.toString()));
		if (checkExist(query2,qid2)) {
			clearInterval(loop_clickAndCheck);
			if (typeof callback == "function") {
				callback();
			}
		}else{
			if (checkExist(query1,qid1)) {
				if (old_top==document.querySelectorAll(query1)[qid1].getBoundingClientRect().top && old_left==document.querySelectorAll(query1)[qid1].getBoundingClientRect().left) {
					if (match % ticks == 0) {
						clickNow(query1,qid1,msg);
					}
					match += 1;
				}else{
					old_top = document.querySelectorAll(query1)[qid1].getBoundingClientRect().top;
					old_left = document.querySelectorAll(query1)[qid1].getBoundingClientRect().left;
				}
			}
		}
	}, 100);
}

function popUpNotEnough(rep) {
	const query = ".btn-use-full.index-1",
		qid = 0,
		msg = message.replenish.elixir.half_elixir.use;
	let cmd = [], coordinate, consumable_data;
	consumable_data = my_profile+"Consumable Status:";
	for (let i = 0; i < rep.length; i++) {
		consumable_data += ("\n- "+rep[i].name+": "+rep[i].number);
	}
	let init_popUpNotEnough = function() {
		coordinate = getCoord(document.querySelectorAll(query)[qid]);
		if (coordinate!==0){
			cmd.push({"cmd":"clickIt","param":coordinate});
			cmd.push({"cmd":"log","level":"process","msg":msg});
			cmd.push({"cmd":"log","level":"summary","msg":consumable_data,"split":0});
			xhr.open('POST', server);
			xhr.send(JSON.stringify(cmd));
		}
	};
	checkEl(query,qid,init_popUpNotEnough);

}

function clickAndCheckSkill(query,qid=0,msg="clickAndCheckSkill called",callback=false,special_case=false){
	let old_class = document.querySelectorAll(query)[qid].parentNode.classList[0];
	let loop_clickAndCheckSkill = setInterval(function() {
		console.log(checkEl.name + " " + query + "[" + qid + "]");
		if (Array.from(document.querySelectorAll(query)[qid].parentNode.parentNode.classList).indexOf("tmp-mask")>=0 || Array.from(document.querySelectorAll(query)[qid].parentNode.parentNode.classList).indexOf("btn-ability-unavailable")>=0){
			clearInterval(loop_clickAndCheckSkill);
			console.log(clickAndCheckSkill.name + " case normal");
			if (typeof callback == "function") {
				callback();
			}
		// Bea skill
		}else if(special_case===1 && document.querySelectorAll(query)[qid].parentNode.classList[0] != old_class){
			clearInterval(loop_clickAndCheckSkill);
			console.log(clickAndCheckSkill.name + " case " + special_case.toString());
			if (typeof callback == "function") {
				callback();
			}
		// Out of sight & sage of eternity
		}else if(special_case===2){
			let do_click = true;
			console.log(clickAndCheckSkill.name + " case " + special_case.toString());
			let popup_query = "#wrapper > div.contents > div.pop-usual.pop-select-member > div.prt-popup-header";
			if (checkExist(popup_query,0)) {
				if (document.querySelector("#wrapper > div.contents > div.pop-usual.pop-select-member > div.prt-popup-header").innerHTML == "Use Skill"){
					clearInterval(loop_clickAndCheckSkill);
					do_click = false;
					if (typeof callback == "function") {
						callback();
					}
				}
			}
			if (do_click) {
				if (checkExist(query,qid)) {
					clickNow(query,qid,msg);
				}
			}
		}else{
			if (checkExist(query,qid)) {
				clickNow(query,qid,msg);
			}
		}

	}, 500);
}

function getCharStr(char_id){
	let char;
	if (char_id==1){
		char = "MC";
	}else{
		char = "NPC"+((char_id-1).toString());
	}
	return char;
}

function useSkill(char_id,abi_id,callback=false,special_case=false){
	console.log(useSkill.name + ", char: "+char_id+", ability: " + (abi_id.toString()) + ", case: "+special_case);
	let char = getCharStr(char_id);
	abi_id = parseInt(abi_id)-1;
	// console.log("lol");
	console.log(".prt-command-chara.chara"+(char_id.toString())+">div>div.lis-ability");
	if (Array.from(document.querySelectorAll(".prt-command-chara.chara"+(char_id.toString())+">div>div.lis-ability")[abi_id].classList).indexOf("btn-ability-available")>=0 && document.querySelectorAll(".prt-command-chara.chara"+(char_id.toString())+">div>div.lis-ability")[abi_id].getBoundingClientRect().width>0){
		clickAndCheckSkill(".prt-command-chara.chara"+(char_id.toString())+">div>div>div>.img-ability-icon",abi_id,my_profile+"Clicking "+char+" skill"+((abi_id+1).toString()),callback,special_case);
	}else{
		if (typeof callback == "function") {
			callback();
		}
	}
}

function clickBack(callback=false){
	clickAndCheck(".btn-command-back.display-on",0,"div.prt-member",0,my_profile+"Clicking back",callback,10);
}

function clickSummonPanel(callback=false){
	let query1 = ".prt-list-top.btn-command-summon.summon-on";
	let query2 = ".prt-summon-list.opened";
	let query3 = ".prt-list-top.btn-command-summon.summon-off";
	let qid1 = 0, qid2 = 0, qid3 = 0;
	let msg = my_profile+"Clicking summon panel";
	let old_top = -1;
	let old_left = -1;
	let loop_clickAndCheck = setInterval(function() {
		console.log(clickAndCheck.name + ", check: " + query2 + "["+(qid2.toString())+"], click: " + query1 + "["+(qid1.toString())+"]");
		if (checkExist(query2,qid2) || checkExist(query3,qid3)) {
			clearInterval(loop_clickAndCheck);
			if (typeof callback == "function") {
				callback();
			}
		}else{
			if (checkExist(query1,qid1)) {
				if (old_top==document.querySelectorAll(query1)[qid1].getBoundingClientRect().top && old_left==document.querySelectorAll(query1)[qid1].getBoundingClientRect().left) {
					clickNow(query1,qid1,msg);
				}else{
					old_top = document.querySelectorAll(query1)[qid1].getBoundingClientRect().top;
					old_left = document.querySelectorAll(query1)[qid1].getBoundingClientRect().left;
				}
			}
		}
	}, 200);
	// clickAndCheck(,0,,0,);
}

function clickSummon(summon_id,callback1=false,callback2=false){
	summon_id = summon_id-1;
	if (Array.from(document.querySelectorAll(".lis-summon")[summon_id].classList).indexOf("btn-summon-available")>=0){
		let loop_clickSummon = setInterval(function() {
			if (document.querySelectorAll(".lis-summon>img")[summon_id].getBoundingClientRect().x=== 72 + (summon_id * 51)){
				clearInterval(loop_clickSummon);
				clickAndCheck(".lis-summon>img",summon_id,".pop-usual.pop-summon-detail>div>.btn-usual-ok.btn-summon-use",0,my_profile+"Clicking summon "+((summon_id+1).toString()),callback1);
			}
		}, 300);
	}else{
		if (typeof callback2 == "function") {
			callback2();
		}
	}
}

function clickOkSummon(callback=false){
	let el_ok = ".pop-usual.pop-summon-detail>div>.btn-usual-ok.btn-summon-use";
	if (document.querySelector(el_ok) !== null){
		clickAndCheck(el_ok,0,"div.prt-member",0,my_profile+"Clicking summon ok",callback);
	}else{
		if (typeof callback == "function") {
			callback();
		}
	}
}
function clickOkSummon2(summon_id,callback=false){
	let el_ok = ".pop-usual.pop-summon-detail>div>.btn-usual-ok.btn-summon-use";
	let summon_el = '.lis-summon[pos="'+(summon_id.toString())+'"]';
	if (document.querySelector(el_ok) !== null){
		let loop_clickOkSummon2 = setInterval(function() {
			console.log(clickOkSummon2.name + ", click: " + el_ok + "[0]");
			if (Array.from(document.querySelector(summon_el).classList).indexOf("tmp-mask")>=0 || Array.from(document.querySelector(summon_el).classList).indexOf("btn-summon-unavailable")>=0) {
				clearInterval(loop_clickOkSummon2);
				if (typeof callback == "function") {
					callback();
				}
			}else{
				if (checkExist(el_ok,0)) {
					clickNow(el_ok,0,my_profile+"Clicking summon ok2");
				}
			}
		}, 1000);
	}else{
		if (typeof callback == "function") {
			callback();
		}
	}
}

function selectSummon(preferred_summon,is_trial=false){
	reload(20);

	let init_selectSummon = function() {
		console.log(init_selectSummon.name);
		reload(10);
		const attrib_list = [6,0,1,2,3,4,5];
		let query_summon_list = ".btn-supporter.lis-supporter";
		let el_summon_list = document.querySelectorAll(query_summon_list);
		let preferred_summon_id = false;
		let picked_attrib_id = false;
		let picked_summon_id = false;
		let picked_is_friend = false;
		let is_friend;
		let picked_summon_stars = false;
		let picked_summon_level = false;
		let picked_summon_plus = false;
		let msg;
		let cmd = [], summon_list = {};
		if (el_summon_list.length>50 && document.querySelector(".prt-supporter-battle-announce")===null && document.querySelector(".txt-confirm-comment")===null && document.querySelector(".prt-check-auth")===null && document.querySelector(".btn-check-auth")===null){
			msg = my_profile+"Verify not appear, summon list length is "+(el_summon_list.length.toString());
			console.log(msg);

			// check if raid is trial
			if (!is_trial){
				console.log("not trial");
				for (let i = 0; i < el_summon_list.length; i++) {
					let match_preferred = false, replace = false;
					let temp_var, summon_detail, summon_name, summon_level, summon_stars, summon_plus;
					temp_var = el_summon_list[i].querySelector(".prt-supporter-summon");
					summon_detail = temp_var.innerHTML.trim();
					temp_var = el_summon_list[i].querySelector(".prt-supporter-summon");
					summon_detail = temp_var.innerHTML.trim();
					summon_name = summon_detail.substring(summon_detail.indexOf("</span>")+8,summon_detail.length);
					summon_level = parseInt(temp_var.children[0].innerHTML.replace("Lvl ",""));
					temp_var = Array.from(el_summon_list[i].querySelector(".prt-summon-skill").classList);
					if (temp_var.indexOf("bless-rank2-style")>=0){
						summon_stars = 4;
					}else if (temp_var.indexOf("bless-rank1-style")>=0){
						summon_stars = 3;
					}else{
						summon_stars = 0;
					}
					temp_var = el_summon_list[i].querySelector(".prt-summon-quality");
					if (temp_var !== null){
						summon_plus = parseInt(temp_var.innerHTML.replace("+",""));
					}else{
						summon_plus = 0;
					}
					temp_var = false;
					is_friend = Array.from(el_summon_list[i].querySelector(".prt-supporter-name").classList).indexOf("ico-friend")>=0;

					// console.log([summon_name,summon_level,summon_stars,summon_plus,is_friend]);

					// loop preferred summon list (specified in parameter)
					for (let j = 0; j < preferred_summon.length; j++) {
						if (preferred_summon[j][0]==summon_name && preferred_summon[j][1]<=summon_stars){
							match_preferred = true;
							temp_var = j;
						}
					}


					if (match_preferred){
						if (picked_attrib_id===false && picked_summon_id===false){
							replace = true;
						}else{
							if (preferred_summon_id>temp_var){
								replace = true;
							}else if(preferred_summon_id==temp_var){
								if (summon_stars>picked_summon_stars){
									replace = true;
								}else if(summon_stars==picked_summon_stars){
									if (picked_is_friend && !is_friend){
										replace = true;
									}else if(!picked_is_friend && !is_friend){
										if (summon_level>picked_summon_level){
											replace = true;
										}else if(summon_level==picked_summon_level){
											if (summon_plus>picked_summon_plus){
												replace = true;
											}
										}
									}
								}
							}
						}
					}
					if (replace){
						picked_attrib_id = Array.from(document.querySelectorAll(".prt-supporter-attribute")).indexOf(el_summon_list[i].parentElement);
						picked_summon_id = i;
						preferred_summon_id = temp_var;
						picked_summon_stars = summon_stars;
						picked_is_friend = is_friend;
						picked_summon_level = summon_level;
						picked_summon_plus = summon_plus;
					}
				}
				console.log([picked_attrib_id,picked_summon_id,preferred_summon_id]);
				if (picked_summon_id===false){
					console.log("go to trial");
					cmd.push({"cmd":"log","level":"process","msg":message.summon.not_found});
					xhr.open("POST", server);
					xhr.send(JSON.stringify(cmd));
					gotoHash("trial");
				}else{
					console.log("summon_found");
					let pickSummon = function() {
						scrollTo(query_summon_list,picked_summon_id);
						clickEl(query_summon_list,picked_summon_id,message.summon.select);
					};
					let clickAndCheckSummon = function(callback=false){
						let el_tab_ele_ico = ".prt-type-text";
						let el_summon_container = ".prt-supporter-attribute";
						let loop_clickAndCheckSummon = setInterval(function() {
							console.log(clickAndCheckSummon.name + ", check: " + el_summon_container + "[" + picked_attrib_id + "], click: " + el_tab_ele_ico + "["+(attrib_list[picked_attrib_id].toString())+"]");
							if (Array.from(document.querySelectorAll(el_summon_container)[picked_attrib_id].classList).indexOf("disableView") == -1) {
								clearInterval(loop_clickAndCheckSummon);
								if (typeof callback == "function") {
									callback();
								}
							}else{
								if (checkExist(el_tab_ele_ico, attrib_list[picked_attrib_id])) {
									clickNow(el_tab_ele_ico, attrib_list[picked_attrib_id], message.summon.pick_tab);
								}
							}
						}, 300);
					};
					clickAndCheckSummon(pickSummon);
				}
			}else{
				console.log("is trial");
				query_summon_list = ".prt-supporter-attribute:not(.disableView)>.btn-supporter.lis-supporter";
				// clearInterval(reload_counter);
				el_summon_list = document.querySelectorAll(query_summon_list);
				// console.log(el_summon_list);
				for (let i = 0; i < el_summon_list.length; i++) {
					is_friend = Array.from(el_summon_list[i].querySelector(".prt-supporter-name").classList).indexOf("ico-friend")>=0;
					if (!is_friend){
						if (picked_summon_id===false){
							picked_summon_id = i;
						}
					}
				}
				// console.log(picked_summon_id);
				if (picked_summon_id!==false){
					scrollTo(".prt-supporter-attribute:not(.disableView)>.btn-supporter.lis-supporter",picked_summon_id);
					clickEl(".prt-supporter-attribute:not(.disableView)>.btn-supporter.lis-supporter",picked_summon_id,message.summon.select);
				}
			}
		}else{
			msg = my_profile+"Verify might appear, summon list length is "+(el_summon_list.length.toString());
			clearInterval(reload_counter);
			console.log(msg);
			cmd.push({"cmd":"log","level":"process","msg":msg});
			cmd.push({"cmd":"log","level":"notif","msg":msg});
			xhr.open("POST", server);
			xhr.send(JSON.stringify(cmd));
		}
	};
	checkEl(".prt-supporter-title",0,init_selectSummon);
}

function doChat(callback=false) {
	console.log(doChat.name);
	let clickDialog = function() {
		console.log(clickDialog.name);
		clickAndNegCheck(query.battle_ui.chat_pop_up.dialog,0,my_profile+"Clicking chat dialog",callback);
	};
	let clickChat = function() {
		console.log(clickChat.name);
		if (checkExist(query.battle_ui.chat+">.ico-attention",0)) {
			clickAndCheck(query.battle_ui.chat,0,query.battle_ui.chat_pop_up.dialog,0,my_profile+"Clicking chat pop up",clickDialog,20);
		}else{
			if (typeof callback == "function") {
				callback();
			}
		}
	};
	checkEl(query.battle_ui.chat,0,clickChat);
}

function backFromTrial(){
	let cmd = [];
	cmd.push({"cmd":"log","level":"process","msg":message.raid.trial.end});
	xhr.open("POST", server);
	xhr.send(JSON.stringify(cmd));
	gotoHash("main");
}

function gotoResult() {
	console.log(gotoResult.name);
	console.log(is_host);
	if (is_host || window.location.hash.indexOf("#raid/")>=0) {
		gotoHash("quest");
	}else if (window.location.hash.indexOf("#raid_multi")>=0) {
		reloadNow();
	}
}

function attack(rep){
	console.log(attack.name);
	let cmd = [];
	let reps = rep.scenario;
	let win = false;
	let is_last_raid = false;
	let ougi = 0;
	let msg = "";
	let pos_player = ["MC","NPC1","NPC2","NPC3","NPC4","NPC5"];
	for (let i = 0; i < reps.length; i++) {
		if (reps[i].cmd =="win"){
			if (reps[i].is_last_raid){is_last_raid=true;}
			win=true;
		}else if (reps[i].cmd=="special" || reps[i].cmd=="special_npc"){
			msg += my_profile+pos_player[reps[i].pos]+" used ougi \""+reps[i].name+"\".\n";
			if (reps[i].total){msg += my_profile+pos_player[reps[i].pos]+" dealt "+reps[i].total[0].split.join("")+" damage.\n";}
			ougi++;
		}else if (reps[i].cmd=="attack" && reps[i].from=="player"){
			if (reps[i].damage.length==3){
				msg += my_profile+pos_player[reps[i].pos]+" made a triple attack.\n";
			}else if (reps[i].damage.length==2){
				msg += my_profile+pos_player[reps[i].pos]+" made a double attack.\n";
			}
			msg += my_profile+pos_player[reps[i].pos]+ " dealt ";
			for (let ii=0; ii<reps[i].damage.length; ii++){
				msg += reps[i].damage[ii][0].value.toString();
				if (ii<reps[i].damage.length-1){
					msg += ", ";
				}else{
					msg += " damage.\n";
				}
			}
		}
	}

	if(win){
		cmd.push({"cmd":"log","level":"process","msg":msg+my_profile+"Foe defeated."});
	}else{
		cmd.push({"cmd":"log","level":"process","msg":msg+my_profile+"Foe is still alive."});
		cmd.push({"cmd":"press","key":"f5"});
	}
	xhr.open('POST', server);
	xhr.send(JSON.stringify(cmd));
	if(win && is_last_raid){
		gotoResult();
	}else if(win){
		clickEl(".btn-result",0,my_profile+"Go to next round");
	}
}

function skillUsed(rep){
	console.log(skillUsed.name);
	let do_reload = false;
	let reps = rep.scenario;
	let win = false, is_last_raid = false;
	// win = false;
	// is_last_raid = false;
	console.log(reps);
	for (let i = 0; i < reps.length; i++) {
		const scenario = reps[i];
		if (scenario.cmd =="ability"){
			if (scenario.name == "Thunder Raid") {
				do_reload = true;
			}
		}else if (scenario.cmd =="damage") {
			if (scenario.to == "player") {
				for (let j = 0; j < scenario.list.length; j++) {
					const element = scenario.list[j];
					if (element.hp !== undefined && element.pos !== undefined) {
						player_status[element.pos].hp = element.hp;
					}
				}
			}
		}else if (scenario.cmd =="finished"){
			win=true;
			is_last_raid=true;
		}else if (scenario.cmd == "win"){
			if (scenario.is_last_raid){is_last_raid=true;}
			win=true;
		}
		
	}

	if(win && is_last_raid){
		gotoResult();
	}else if(do_reload){
		reloadNow();
	}
}

function potUsed(rep) {
	console.log(potUsed.name);
	let reps = rep.scenario;
	for (let i = 0; i < reps.length; i++) {
		const scenario = reps[i];
		if (scenario.cmd == "heal") {
			for (let j = 0; j < scenario.list.length; j++) {
				const element = scenario.list[j];
				if (element.hp !== undefined && element.pos !== undefined) {
					player_status[element.pos].hp = element.hp;
				}
			}
		}
	}
}

function raidFinish(rep){
	console.log(raidFinish.name);
	reload(10);
	let cmd = [];
	let check_timer = true;
	cmd.push({"cmd":"log","level":"process","msg":message.raid.finish});
	let reward_list = {};
	let loop_list = [1,2,3,4,11];

	for (let l in loop_list){
		if (Object.keys(rep.rewards.reward_list[loop_list[l]]).length){
			let keys = [];
			for(let k in rep.rewards.reward_list[loop_list[l]]) keys.push(k);
			for(let i in keys){
				if(reward_list[rep.rewards.reward_list[loop_list[l]][keys[i]].name]){
					reward_list[rep.rewards.reward_list[loop_list[l]][keys[i]].name] += parseInt(rep.rewards.reward_list[loop_list[l]][keys[i]].count);
				}else{
					reward_list[rep.rewards.reward_list[loop_list[l]][keys[i]].name] = parseInt(rep.rewards.reward_list[loop_list[l]][keys[i]].count);
				}
			}
		}
	}
	if (tracked_item !== false){
		let track_item = my_profile+"Current Status:";
		let temp_str;
		for (let item in tracked_item){
			if (tracked_item.hasOwnProperty(item)) {
		        temp_str = "\n- "+tracked_item[item].name+": "+(tracked_item[item].number).toString();
		        track_item += temp_str;
		    }
		}
		cmd.push({"cmd":"log","level":"summary","msg":track_item,"split":0});
	}
	cmd.push({"cmd":"reward","payload":reward_list});
	if (check_timer){
		cmd.push({"cmd":"check_timer"});
	}
	xhr.open('POST', server);
	xhr.send(JSON.stringify(cmd));
	let gotoMain = function() {gotoHash("main");};
	checkEl(".mask",0,gotoMain);
}