GBF Lib

GBF Bot Library

Verzia zo dňa 03.06.2019. Pozri najnovšiu verziu.

Tento skript by nemal byť nainštalovaný priamo. Je to knižnica pre ďalšie skripty, ktorú by mali používať cez meta príkaz // @require https://update.greasyfork.org/scripts/383201/704452/GBF%20Lib.js

// ==UserScript==
// @name         GBF Lib
// @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);
}